CC2541 无法驱动 SHT20 温湿度传感器的原因
时间:10-02
整理:3721RD
点击:
单独在一个工程里面使用 SHT20就没有问题,但是把它移植到 CC2541 的蓝牙工程里面,读到的数据就有问题,我百思不得其姐。有一次单步仿真的时候,发现有些代码居然直接跳过去了,仿真一下子跳了几行,不知道怎么回事。
后来想是不是IAR的设置,把这几步优化掉了,然后去对比2个工程的设置。发现优化等级是 high, 把优化等级降低,正确读到温湿度数据。
原来罪魁祸首是优化等级。至此困扰我1天的原因解决。
下面是CC2541的代码。我也是参考别人的,移植到2541上的。到原作者不记得是谁了,别见怪
#include <hal_types.h>
#include <ioCC254x_bitdef.h>
#include "ioCC2541.h"
//#include <intrins.h>
#include "SHT20.h"
#define add_w 0x80 //传感器地址 + 写操作
#define add_r 0x81 //传感器地址 + 读操作
#define T_code 0xe3 //温度 测量指令
#define RH_code 0xe5 //湿度 测量指令
#define user_code_w 0xe6 //用户寄存器 写指令
#define user_code_r 0xe7 //用户寄存器 读指令,可读电池电压是否小于2.25V。(测量后才可查看)
#define RST_code 0xfe //软复位,寄存器服务。
#define uchar unsigned char
#define uint unsigned int
//究竟会是什么原因导致的数据不正常?
//sbit sht20_sda=P1^3; //数据线
//sbit sht20_scl=P1^4; //时钟线
#define sht20_sda P1_7
#define sht20_scl P1_6
/***********延时程序***********/
//11.0592MHz 1T 时钟周期0.09042us 机器周期0.09042us,根据当前配置计算延时程序。
//测量分辨率 RH 12 BIT、T 14 BIT,测量时间RH29ms、T85ms
//测量分辨率 RH 8 BIT、T 12 BIT,测量时间RH4 ms、T22ms
//sht20_scl时钟,延时2us
void delay85ms(void) //误差 -0.000000000011us
{
unsigned int a,b,c;
for(c=397;c>0;c--)
//for(c=97;c>0;c--)
for(b=56;b>0;b--)
for(a=85;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
}
void delay29ms(void) //误差 -0.072337962967us
{
unsigned int a,b,c;
for(c=361;c>0;c--)
//for(c=161;c>0;c--)
for(b=221;b>0;b--)
for(a=3;a>0;a--);
NOP(); //if Keil,require use intrins.h
}
void delay15ms(void) //误差 -0.000000000002us
{
unsigned int a,b;
for(b=520;b>0;b--)
//for(b=220;b>0;b--)
for(a=187;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
}
/*void delay4ms(void) //误差 -0.072337962963us
{
unsigned char a,b;
for(b=89;b>0;b--)
for(a=247;a>0;a--);
}
void delay22ms(void) //误差 -0.036168981484us
{
unsigned char a,b,c;
for(c=9;c>0;c--)
for(b=170;b>0;b--)
for(a=78;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
} */
void delay2us(void) //误差 -0.010706018519us
{
unsigned char a,b;
for(b=5;b>0;b--)
for(a=8;a>0;a--);
}
/***********时序程序***********/
//传感器 基本时序程序。
//1 启动
//2 停止
//3 应答&非应答
//4 接收应答
//5 发送 一字节
//6 接收 一字节
//1 启动
void sht20_start(void)
{
sht20_sda=1;
delay2us();
sht20_scl=1;
delay2us();
sht20_sda=0;
delay2us();
sht20_scl=0;
delay2us();
}
//2 停止
void sht20_stop(void)
{
sht20_sda=0;
delay2us();
sht20_scl=1;
delay2us();
sht20_sda=1;
delay2us();
sht20_scl=0;
delay2us();
}
//3 应答&非应答
void sht20_ACK (void)
{
sht20_sda=0;
delay2us();
sht20_scl=1;
delay2us();
sht20_scl=0;
delay2us();
}
void sht20_noACK (void)
{
sht20_scl=1;
delay2us();
sht20_sda=0;
sht20_scl=0;
delay2us();
}
//4 接收应答
//bit sht20_getACK(void)
unsigned char sht20_getACK(void)
{
unsigned char ack1=0;
//bit ack1 = 0;
sht20_sda=1;
delay2us();
sht20_scl=1;
delay2us();
ack1=sht20_sda;
sht20_scl=0;
delay2us();
return ack1;
}
//5 发送 一字节,代码都是一样的?
//在CC2541里面,位是怎么操作的?
void sht20_send(uchar send_data)
{
uchar Bit_Counter=8;
while(Bit_Counter>0)
{
//高位数据在前?那么如何换成一个位?
//sht20_sda=(bit)(DATA&0x80);
if(send_data&0x80)
sht20_sda = 1;
else
sht20_sda = 0;
send_data<<=1;
sht20_scl=1;
delay2us();
sht20_scl=0;
delay2us();
Bit_Counter--;
}
}
//6 接收 一字节
unsigned char sht20_read()
{
unsigned char x=0,y=8;
sht20_sda=1;
while(y>0)
{
sht20_scl=1;
delay2us();
if(sht20_sda)
x=x|0x01;
else
x=x&0xfe;
sht20_scl=0;
delay2us();
if(y>1)
x=x<<1;
y--;
}
return x;
}
/*1**********传感器初始化&软复位*********/
/*2**********传感器用户寄存器读取*******/
/*3**********传感器测量分辨率设置*******/
/*4**********传感器低电压检测***********/
// 1传感器初始化&软复位
void SHT2x_init()
{
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(RST_code);
sht20_getACK();
sht20_stop();
delay15ms();
sht20_sda=1;
sht20_scl=1;
}
// 2传感器用户寄存器读取
unsigned char SHT2x_user_register()
{
uchar register_data;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_r);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
register_data=sht20_read();
sht20_noACK();
sht20_stop();
return register_data;
}
// 3 传感器测量分辨率设置
// 测量分辨率设置 RH 8 BIT、T 12 BIT,测量时间RH4ms、T22ms
void SHT2x_Resolution()
{
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_w);
sht20_getACK();
sht20_send(0x3b);
sht20_getACK();
sht20_getACK();
sht20_stop();
}
// 4 传感器低电压检测
// 此状态位在每次测量后更新
//bit SHT2x_battery()
unsigned char SHT2x_battery()
{
uchar battery;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_r);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
battery=sht20_read();
sht20_noACK();
sht20_stop();
battery=(battery&0x40)>>6;
return battery;
}
/***********测量结果***********/
// 1 湿度测量
// 启动》发送地址+写操作》接收ACK》湿度测量命令》接收ACK》启动》发送地址+读操作》...
// ...接收ACK》测量时间延时》读取高位数据》ACK》读取低位数据》NO_ACK》停止。
// 计算结果。返回结果。
unsigned int RH_Result()
{
unsigned int RH_Data;
unsigned long RH=0;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(RH_code);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
delay29ms();
RH_Data=sht20_read();
sht20_ACK();
RH_Data=RH_Data<<8;
RH_Data=RH_Data|sht20_read();
sht20_noACK();
sht20_stop();
RH_Data=RH_Data&0xfffc;
RH=RH_Data*12500L;
RH=RH>>16;
RH=RH-600;
return RH;
}
// 2 温度测量
// 启动》发送地址+写操作》接收ACK》温度测量命令》接收ACK》启动》发送地址+读操作》...
// ...接收ACK》测量时间延时》读取高位数据》ACK》读取低位数据》NO_ACK》停止。
// 计算结果。返回结果。
unsigned int T_Result()
{
unsigned int T_Data;
unsigned long T=0;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(T_code);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
delay85ms();
T_Data=sht20_read();
sht20_ACK();
T_Data=T_Data<<8;
T_Data=T_Data|sht20_read();
sht20_noACK();
sht20_stop();
T_Data=T_Data&0xfffE;
T=T_Data*17572L;
T=T>>16;
T=T-4685;
return T;
}
//这个函数需要实现,具体看硬件电路怎么设计的
//难道是堆栈的原因,也不像,其实是程序飞了
void sht20_gpio_init(void)
{
P1SEL &= BIT6 ;
P1SEL &= BIT7; // Function as General Purpose I/O.
//P1_0 = 1; // LED1 on.
P1DIR |= BIT6 + BIT7; // Output.
P1_6 = 1;
P1_7 = 1;
}
void sht20_config(void)
{
uint B1;//B1有什么用途
SHT2x_init();
SHT2x_Resolution();
B1=SHT2x_user_register();
}
/***********主程序***********/
//void sht20_conver_start()
//{
// uint T,RH,B1;
// T=T_Result();
// RH=RH_Result();
// SHT2x_battery();
//}
extern sys_param_data_t sys_data_used_qhq;
/***********主程序***********/
void sht20_conver_start()
{
uint temper_data,humitu_data,B1;
temper_data = T_Result();
humitu_data=RH_Result();
sys_data_used_qhq.temper_data[0] = temper_data/256;
sys_data_used_qhq.temper_data[1] = temper_data%256;
sys_data_used_qhq.humitu_data[0] = humitu_data/256;
sys_data_used_qhq.humitu_data[1] = humitu_data%256;
SHT2x_battery();
}
欢迎光临小弟淘宝店:https://shop116994086.taobao.com ... 1997079397.2.ecENAL
后来想是不是IAR的设置,把这几步优化掉了,然后去对比2个工程的设置。发现优化等级是 high, 把优化等级降低,正确读到温湿度数据。
原来罪魁祸首是优化等级。至此困扰我1天的原因解决。
下面是CC2541的代码。我也是参考别人的,移植到2541上的。到原作者不记得是谁了,别见怪
#include <hal_types.h>
#include <ioCC254x_bitdef.h>
#include "ioCC2541.h"
//#include <intrins.h>
#include "SHT20.h"
#define add_w 0x80 //传感器地址 + 写操作
#define add_r 0x81 //传感器地址 + 读操作
#define T_code 0xe3 //温度 测量指令
#define RH_code 0xe5 //湿度 测量指令
#define user_code_w 0xe6 //用户寄存器 写指令
#define user_code_r 0xe7 //用户寄存器 读指令,可读电池电压是否小于2.25V。(测量后才可查看)
#define RST_code 0xfe //软复位,寄存器服务。
#define uchar unsigned char
#define uint unsigned int
//究竟会是什么原因导致的数据不正常?
//sbit sht20_sda=P1^3; //数据线
//sbit sht20_scl=P1^4; //时钟线
#define sht20_sda P1_7
#define sht20_scl P1_6
/***********延时程序***********/
//11.0592MHz 1T 时钟周期0.09042us 机器周期0.09042us,根据当前配置计算延时程序。
//测量分辨率 RH 12 BIT、T 14 BIT,测量时间RH29ms、T85ms
//测量分辨率 RH 8 BIT、T 12 BIT,测量时间RH4 ms、T22ms
//sht20_scl时钟,延时2us
void delay85ms(void) //误差 -0.000000000011us
{
unsigned int a,b,c;
for(c=397;c>0;c--)
//for(c=97;c>0;c--)
for(b=56;b>0;b--)
for(a=85;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
}
void delay29ms(void) //误差 -0.072337962967us
{
unsigned int a,b,c;
for(c=361;c>0;c--)
//for(c=161;c>0;c--)
for(b=221;b>0;b--)
for(a=3;a>0;a--);
NOP(); //if Keil,require use intrins.h
}
void delay15ms(void) //误差 -0.000000000002us
{
unsigned int a,b;
for(b=520;b>0;b--)
//for(b=220;b>0;b--)
for(a=187;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
}
/*void delay4ms(void) //误差 -0.072337962963us
{
unsigned char a,b;
for(b=89;b>0;b--)
for(a=247;a>0;a--);
}
void delay22ms(void) //误差 -0.036168981484us
{
unsigned char a,b,c;
for(c=9;c>0;c--)
for(b=170;b>0;b--)
for(a=78;a>0;a--);
NOP(); //if Keil,require use intrins.h
NOP(); //if Keil,require use intrins.h
} */
void delay2us(void) //误差 -0.010706018519us
{
unsigned char a,b;
for(b=5;b>0;b--)
for(a=8;a>0;a--);
}
/***********时序程序***********/
//传感器 基本时序程序。
//1 启动
//2 停止
//3 应答&非应答
//4 接收应答
//5 发送 一字节
//6 接收 一字节
//1 启动
void sht20_start(void)
{
sht20_sda=1;
delay2us();
sht20_scl=1;
delay2us();
sht20_sda=0;
delay2us();
sht20_scl=0;
delay2us();
}
//2 停止
void sht20_stop(void)
{
sht20_sda=0;
delay2us();
sht20_scl=1;
delay2us();
sht20_sda=1;
delay2us();
sht20_scl=0;
delay2us();
}
//3 应答&非应答
void sht20_ACK (void)
{
sht20_sda=0;
delay2us();
sht20_scl=1;
delay2us();
sht20_scl=0;
delay2us();
}
void sht20_noACK (void)
{
sht20_scl=1;
delay2us();
sht20_sda=0;
sht20_scl=0;
delay2us();
}
//4 接收应答
//bit sht20_getACK(void)
unsigned char sht20_getACK(void)
{
unsigned char ack1=0;
//bit ack1 = 0;
sht20_sda=1;
delay2us();
sht20_scl=1;
delay2us();
ack1=sht20_sda;
sht20_scl=0;
delay2us();
return ack1;
}
//5 发送 一字节,代码都是一样的?
//在CC2541里面,位是怎么操作的?
void sht20_send(uchar send_data)
{
uchar Bit_Counter=8;
while(Bit_Counter>0)
{
//高位数据在前?那么如何换成一个位?
//sht20_sda=(bit)(DATA&0x80);
if(send_data&0x80)
sht20_sda = 1;
else
sht20_sda = 0;
send_data<<=1;
sht20_scl=1;
delay2us();
sht20_scl=0;
delay2us();
Bit_Counter--;
}
}
//6 接收 一字节
unsigned char sht20_read()
{
unsigned char x=0,y=8;
sht20_sda=1;
while(y>0)
{
sht20_scl=1;
delay2us();
if(sht20_sda)
x=x|0x01;
else
x=x&0xfe;
sht20_scl=0;
delay2us();
if(y>1)
x=x<<1;
y--;
}
return x;
}
/*1**********传感器初始化&软复位*********/
/*2**********传感器用户寄存器读取*******/
/*3**********传感器测量分辨率设置*******/
/*4**********传感器低电压检测***********/
// 1传感器初始化&软复位
void SHT2x_init()
{
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(RST_code);
sht20_getACK();
sht20_stop();
delay15ms();
sht20_sda=1;
sht20_scl=1;
}
// 2传感器用户寄存器读取
unsigned char SHT2x_user_register()
{
uchar register_data;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_r);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
register_data=sht20_read();
sht20_noACK();
sht20_stop();
return register_data;
}
// 3 传感器测量分辨率设置
// 测量分辨率设置 RH 8 BIT、T 12 BIT,测量时间RH4ms、T22ms
void SHT2x_Resolution()
{
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_w);
sht20_getACK();
sht20_send(0x3b);
sht20_getACK();
sht20_getACK();
sht20_stop();
}
// 4 传感器低电压检测
// 此状态位在每次测量后更新
//bit SHT2x_battery()
unsigned char SHT2x_battery()
{
uchar battery;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(user_code_r);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
battery=sht20_read();
sht20_noACK();
sht20_stop();
battery=(battery&0x40)>>6;
return battery;
}
/***********测量结果***********/
// 1 湿度测量
// 启动》发送地址+写操作》接收ACK》湿度测量命令》接收ACK》启动》发送地址+读操作》...
// ...接收ACK》测量时间延时》读取高位数据》ACK》读取低位数据》NO_ACK》停止。
// 计算结果。返回结果。
unsigned int RH_Result()
{
unsigned int RH_Data;
unsigned long RH=0;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(RH_code);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
delay29ms();
RH_Data=sht20_read();
sht20_ACK();
RH_Data=RH_Data<<8;
RH_Data=RH_Data|sht20_read();
sht20_noACK();
sht20_stop();
RH_Data=RH_Data&0xfffc;
RH=RH_Data*12500L;
RH=RH>>16;
RH=RH-600;
return RH;
}
// 2 温度测量
// 启动》发送地址+写操作》接收ACK》温度测量命令》接收ACK》启动》发送地址+读操作》...
// ...接收ACK》测量时间延时》读取高位数据》ACK》读取低位数据》NO_ACK》停止。
// 计算结果。返回结果。
unsigned int T_Result()
{
unsigned int T_Data;
unsigned long T=0;
sht20_start();
sht20_send(add_w);
sht20_getACK();
sht20_send(T_code);
sht20_getACK();
sht20_start();
sht20_send(add_r);
sht20_getACK();
delay85ms();
T_Data=sht20_read();
sht20_ACK();
T_Data=T_Data<<8;
T_Data=T_Data|sht20_read();
sht20_noACK();
sht20_stop();
T_Data=T_Data&0xfffE;
T=T_Data*17572L;
T=T>>16;
T=T-4685;
return T;
}
//这个函数需要实现,具体看硬件电路怎么设计的
//难道是堆栈的原因,也不像,其实是程序飞了
void sht20_gpio_init(void)
{
P1SEL &= BIT6 ;
P1SEL &= BIT7; // Function as General Purpose I/O.
//P1_0 = 1; // LED1 on.
P1DIR |= BIT6 + BIT7; // Output.
P1_6 = 1;
P1_7 = 1;
}
void sht20_config(void)
{
uint B1;//B1有什么用途
SHT2x_init();
SHT2x_Resolution();
B1=SHT2x_user_register();
}
/***********主程序***********/
//void sht20_conver_start()
//{
// uint T,RH,B1;
// T=T_Result();
// RH=RH_Result();
// SHT2x_battery();
//}
extern sys_param_data_t sys_data_used_qhq;
/***********主程序***********/
void sht20_conver_start()
{
uint temper_data,humitu_data,B1;
temper_data = T_Result();
humitu_data=RH_Result();
sys_data_used_qhq.temper_data[0] = temper_data/256;
sys_data_used_qhq.temper_data[1] = temper_data%256;
sys_data_used_qhq.humitu_data[0] = humitu_data/256;
sys_data_used_qhq.humitu_data[1] = humitu_data%256;
SHT2x_battery();
}
欢迎光临小弟淘宝店:https://shop116994086.taobao.com ... 1997079397.2.ecENAL
出现这种问题,我觉得可能是因为延时造成的。不要用软件延时,能通过定时器延时是最好的了。
SensorTag里有一个SHT21的代码
哈哈!debug时候确实常发生哈!
你这是广告呀!大表哥,这里有广告!