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

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

此问题尚无答案
All Replies
  • 秀才80分

    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;              //设置系统主时钟频率为32MHZ
        
        PERCFG = 0x00;		     //位置1 P0口
        P0SEL = 0x3C;	             //P0用作串口
        P2DIR &= ~0XC0;                  //P0优先作为UART0
        U0CSR |= 0xC0;		     //串口设置为UART方式
        U0GCR  |= 8;		     //波特率设为9600	
        U0BAUD |= 56;	    
        UTX0IF = 1; 
           //UART0 TX中断标志初始置位1
        U0CSR |= 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.1s
            Read_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数据手册P17
    		  T_Data  = (Sensor_Data[2] * 256) + Sensor_Data[3];//保存温度值,见AM2321数据手册P17
    		  mbus_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;          //接收完成
      } 
      else
        Recdata[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_SDA
                       uartbyte('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;
      }
    
    

  • 状元25210分

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

    大秦正声蓝牙电子之家

    http://yang96381.blog.163.com

    手机蓝牙脱机烧录工具,可不用笔记本和台式电脑

    提供德州仪器cc26,cc13,cc25系列脱机烧录工具。

    手机18302938569

     

  • 秀才80分

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

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

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

    大秦正声蓝牙电子之家

    http://yang96381.blog.163.com

    手机蓝牙脱机烧录工具,可不用笔记本和台式电脑

    提供德州仪器cc26,cc13,cc25系列脱机烧录工具。

    手机18302938569