TI中文支持网
TI专业的中文技术问题搜集分享网站

CC2530连接AM2321温湿传感器得不到数据

CC2530连接了AM2321传感器模块,由于是模块化了的板子,所以硬件连接没有任何错误,串口连接电脑,程序上按照AM2321数据手册上的时序图写了Read_Sensor读取函数,只要一进入Read_Sensor(void)读取数据的函数中就会因为传感器没有电平变化响应而跳出,无法获得数据。

#include <iocc2530.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define Sensor_SDA P0_4//定义P0.4为AM2321的数据口
#define SDADirOut P0DIR|=0x10;//xxxx1M01
#define SDADirIn  P0DIR&=0x10;
#define COM_R MDP0_4


unsigned char Sensor_Data[5]={0x00,0x00,0x00,0x00,0x00};//定义温湿度传感器数据存放区。
unsigned char Sensor_Check;//温湿度传感器校验和,判断读取的温湿度数据是否正确。
unsigned char Sensor_AnswerFlag;  //温湿度传感器收到起始标志位
unsigned char Sensor_ErrorFlag;//读取传感器错误标志
unsigned char Ascii_buffer[10] = {'0','1','2','3','4','5','6','7','8','9'};
unsigned char mbus_regi[20] = {'H',':','0','0','.','0','%','R','H',',','T',':','0','0','.','0'};
unsigned int RH_Data;//定义湿度值,起到中转作用,因为其数值一般大于255,所以声明为int 类型
unsigned int T_Data;//定义温度值,起到中转作用 ,因为其数值一般大于255,所以声明为int 类型
unsigned int  Sys_CNT;
unsigned int  Tmp;


char Recdata[100];//接收数据缓存

uchar RXflag = 1;//接收完成标志
uint  datanumber = 0;//接收数据的长度


void delay_10us(uint n);	
void delay_1s(uint n);	
unsigned char Read_SensorData(void); //声明读取AM2321数据函数
unsigned char Read_Sensor(void);  //声明读取AM2321温湿度数据函数

void Delay(uint n);
void InitLED(void);
void initUART0(void);



void delay_1us(uint microSecs) 
{  while(microSecs--){/* 32 NOPs == 1 usecs 因为延时还有计算的缘故,用了31个nop*/asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");asm("nop");} 
}

void Delay(uint n) //延时  如需精确延时请用示波器辅助调试
{uint i,j;for(j = 0; j < 10 ; j++){for(i = 0; i < n ; i++);}
}
void delay_10us(uint n)
{uint tt,yy;for(tt=0;tt<n;tt++);for(yy=310;yy>0;yy--)asm("NOP");
}
void delay_1s(uint n)
{uint tt,ulloop=1000;for(tt=n;tt>0;tt--);for(ulloop=1000;ulloop>0;ulloop--)delay_1us(1000);
}

void initUART0(void)//初始化串口0函数	
{CLKCONCMD &= ~0x40;//设置系统时钟源为32MHZ晶振while(CLKCONSTA & 0x40);//等待晶振稳定CLKCONCMD &= ~0x47;//设置系统主时钟频率为32MHZPERCFG = 0x00;//位置1 P0口P0SEL = 0x3C;//P0用作串口P2DIR &= ~0XC0;//P0优先作为UART0U0CSR |= 0xC0;//串口设置为UART方式U0GCR  |= 8;//波特率设为9600U0BAUD |= 56;UTX0IF = 1;//UART0 TX中断标志初始置位1U0CSR |= 0X40;//允许接收IEN0 |= 0x04;//开总中断,接收中断EA = 1;
}

void uartbyte(char dat)
{U0DBUF=dat;while(UTX0IF==0);UTX0IF=0;
}
void uartstring(char*a)
{for(;*a!=0;a++){uartbyte(*a);}
}
void main(void)
{int i;initUART0();SDADirIn;Sensor_SDA=1;  //SDA数据线由上拉电阻拉高一直保持高电平,初始化数据总线。while(1){delay_1s(1);delay_1us(30000);delay_1us(30000);delay_1us(30000);delay_1us(30000);//延时0.1sRead_Sensor();// 读取传感器数据	if(Sensor_Data[4] == (Sensor_Data[0]+ Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3]))//判断温湿度校验值是否相等,见AM2321数据手册P17.
		{RH_Data = (Sensor_Data[0] * 256) + Sensor_Data[1];//保存湿度值,见AM2321数据手册P17T_Data  = (Sensor_Data[2] * 256) + Sensor_Data[3];//保存温度值,见AM2321数据手册P17mbus_regi[2]	= Ascii_buffer[RH_Data/100]; //取得湿度十位值mbus_regi[3]	= Ascii_buffer[(RH_Data%100)/10];//取得湿度个位值mbus_regi[5]	= Ascii_buffer[RH_Data%10];//取得湿度小数值mbus_regi[12]	= Ascii_buffer[T_Data/100];//取得温度十位值mbus_regi[13]	= Ascii_buffer[(T_Data%100)/10];//取得温度个位值mbus_regi[15]	= Ascii_buffer[T_Data%10];//取得温度小数值for(i = 0; i < 16; i++){uartbyte(mbus_regi[i]);}uartbyte('\r');uartbyte('\n');}}
}
#pragma vector = URX0_VECTOR
 __interrupt void UART0_ISR(void)//串口接收中断处理程序:将接收到的数据赋值给变量temp.
{uchar temp;temp = U0DBUF;if(temp == '#'||temp == '\n')//‘#’结束标识符{Recdata[datanumber++] = '\n';RXflag = 1;//接收完成}elseRecdata[datanumber++] = temp;URX0IF = 0;		//清中断标志
}

unsigned char Read_SensorData(void)		//功能描述:读取单字节的AM2321的数据{int cnt;
	unsigned char i;
	unsigned char buffer,tmp;
	buffer = 0;
	for(i=0;i<8;i++)
	{
		cnt=0;
		while(!Sensor_SDA)	//检测上次低电平是否结束
		{if(++cnt>290){uartbyte('X');break;}
		}
		//延时Min=26us Max50us 跳过数据"0" 的高电平
		delay_1us(35);//延时30us 
		tmp =0;
		if(Sensor_SDA)//延时30us后如果数据口还是高,则该位为1,否则为0,见P19	 
		{tmp = 1;
		}  
		cnt =0;
		while(Sensor_SDA)		//等待高电平 结束
		{	if(++cnt >= 200)
			{uartbyte('V');break;
			}
		}
		buffer <<=1; //移位,使得数据的最低位准备接收下一位
		buffer |= tmp;//把本次接收到的位加入到数据中// uartbyte(buffer);
	}
	return buffer;//返回单字节数据}

unsigned char Read_Sensor(void)//功能描述:读取AM2321的温湿度及校验值放在Sensor_Data[]中。{
	unsigned char i,j;P0SEL &= 0XEF;SDADirOut;P0_4 = 0;//起始信号拉低,见AM2321数据手册P18
	delay_1us(1000);  //延时3Ms,当然一般1ms就可以了。P0_4 = 1; //拉高,释放总线SDADirIn;

	delay_1us(30); //延时30us
	//Sensor_AnswerFlag = 0;  // 传感器响应标志
	if(P0_4 ==0)//从高电平到低电平经过30us(大于20us)是否为低
	{//如果为低,那么传感器发出响应信号Sensor_AnswerFlag = 1;//收到起始信号Sys_CNT = 0;//判断从机是否发出 80us 的低电平响应信号是否结束//delay_1s(3);uartbyte('A');while((!P0_4))	//等待传感器响应信号80us的低电平结束{for(j=0;j<8;j++)delay_1us(10);// Sensor_SDA = 0;if(j>=8) //防止进入死循环{Sensor_ErrorFlag = 1;//Sensor_SDAuartbyte('B');/****接到'B'说明传感器没有响应*****/uartbyte('\t');return 0;}}j=0;Sys_CNT = 0;//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态while((Sensor_SDA))//等待传感器响应信号80us的高电平结束{for(j=0;j<8;j++)delay_1us(10);//  Sensor_SDA = 0;if(j>=8)//防止进入死循环{uartbyte('C');Sensor_ErrorFlag = 1;return 0;}}// 数据接收	传感器共发送40位数据// 即5个字节 高位先送  5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和// 校验和为:湿度高位+湿度低位+温度高位+温度低位for(i=0;i<5;i++){Sensor_Data[i] = Read_SensorData();uartbyte('M');}if((Sensor_Data[0]+Sensor_Data[1]+Sensor_Data[2]+Sensor_Data[3])!=Sensor_Data[4]){for(i=0;i<5;i++){//Am2321_Data[i] = 0x02;}}}else{Sensor_AnswerFlag = 0;uartbyte('Q');// 未收到传感器响应}return 1;}

da qin zheng sheng:

i2c传感器地址是多少?主要检查i2c时序以及引脚是否接上拉电阻?

tao qin1:

回复 da qin zheng sheng:

单总线读的传感器,引脚上拉没问题,提供的案例能在协议栈里面读到。

tao qin1:

回复 tao qin1:

问题已解决,CC2530裸机单总线读取传感器数据对延时要求特别高,望各位小心。网上有人用示波器测试了2530裸机延时相关数据:void Delay_us(uint16 value){
while (value–){
asm("NOP"); //一个指令周期占用一个时钟周期
asm("NOP");
asm("NOP");}}用示波器测试的不同的参数,其时间值如下表:参数值 时间值
75 100us
130 170us
100 130us也就是说value大概为8为延时1us左右。

da qin zheng sheng:

回复 tao qin1:

单总线时序确实严格的,解决问题就好。

赞(0)
未经允许不得转载:TI中文支持网 » CC2530连接AM2321温湿传感器得不到数据
分享到: 更多 (0)