本人在校学生一个,最近做项目时,用到了AM2311温湿度检测模块,这个模块支持IIC和单总线通信方式,IIC通信的例程网上一抓一大把,但是很不巧,小编就误选了单总线通信的模块。
进入正题,如何进行单总线数据通信来读取数据呢?
顾名思义:单总线通信,就是通过一条数据线进行通信.IIC拥有SDA(数据线)和SCL(时钟线),单总线通信,可以理解为去掉了SCL线,通过固定的一套时间协议,达到数据传输的目的。
个人总结:
1.项目实际操作能力有待加强:以前做项目,在网上或多或少都可以找些模块代码进行移植,但是,AM2311单总线通信模块,网上没有相关代码,必须自己撰写,只能依靠模块的数据手册。这一过程花费小编接近2天时间,算是一个小小突破吧。
2.通信协议类的代码,一般精度都很高,在US级别,不要尝试去做一些与读取数据无关的操作,比如延时,比如串口输出接受的某一个数据。(本来AM2311一次性传输数据为40个,小编在其中加了一个pringtf函数,导致接受数据只有24个)
3.一点建议:虽说这样的情况可以突破自我,锻炼个人能力,但是在做一些紧急的项目开发时,最好是选用一些常用的通信方式,更节省时间。
下面贴上几张使用手册的图片。
小编不太清楚具体图片上传是怎么回事,这个手册去各大浏览器搜索,可能也会搜索到的。
话不多说,上代码咯,保证编译之后下载即可使用。
单片机源程序如下:
- #include "am2311.h"
- #include "stm32f10x.h"
- #include "sys.h"
- #include "delay.h"
- AM2311_Data_TypeDef AM2311_Data;
- void AM2311_GPIO_Init1(void)//推挽输出
- {
- GPIO_InitTypeDef GPIO_Initstructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
- GPIO_Initstructure.GPIO_Mode=GPIO_Mode_Out_PP;
- GPIO_Initstructure.GPIO_Pin=GPIO_Pin_7;
- GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOB,&GPIO_Initstructure);
- }
- void AM2311_GPIO_Init2(void)//上拉输入
- {
- GPIO_InitTypeDef GPIO_Initstructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
- GPIO_Initstructure.GPIO_Mode=GPIO_Mode_IPU;
- GPIO_Initstructure.GPIO_Pin=GPIO_Pin_7;
- GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOB,&GPIO_Initstructure);
- }
- void AM2311_GPIO_Init(void)
- {
-
- AM2311_GPIO_Init1();//推挽输出模式配置
- AM2311_GPIO_Init2();//推挽输出模式配置
-
- }
- static uint8_t Read_Byte(void)
- {
- uint8_t i, temp=0;
- for(i=0;i<8;i++)
- {
-
- /*每BIT以50us低电平标志开始,轮询从机发出的50us低电平结束*/
- while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0);//低电平就一直在这里循环,除去开头的低电平50us干扰
-
- delay_us(50); //延时50ms
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1)//如果此时检测还是高电平,代表发送的数据1
- {
- // printf("1");
- while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1);//等待高电平结束
- temp|=(uint8_t)(0x01<<(7-i));//把第七位置一(发送的位是从高到低顺序发送来的)
- }
- else //如果此时为低电平,表示接收到了0
- {
- temp&=(uint8_t)~(0x01<<(7-i)); //
- // printf("0");
- }
- }
- return temp;
- }
- uint8_t Read_AM2311(AM2311_Data_TypeDef *AM2311_Data)
- {
- /*输出模式I*/
- delay_ms(1000);
- delay_ms(1000);
- //第二步:输出1MS低电平,然后将32IO口设置为输入
- AM2311_GPIO_Init1();//引脚设置为输出
- PBout(7)=0;
- delay_ms(1);
- AM2311_GPIO_Init2();//引脚设置成上拉输入,释放总线
- //上边部分应该在read data前初始化一次
- delay_us(30);
- while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==0);//低电平就一直在这里循环
- delay_us(50);//
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1)//表示此时模块即将发送数据,已经成功响应,//问题在于总线电平依旧为低
- {
- // printf("应答信号来了\n");
- while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)==1);//等待响应信号结束
- //开始接受数据
- // printf("NO\n");
-
- AM2311_Data->humi_int=Read_Byte();
- AM2311_Data->humi_deci=Read_Byte();
- AM2311_Data->temp_int=Read_Byte();
- AM2311_Data->temp_deci=Read_Byte();
- AM2311_Data->check_sum=Read_Byte();
- /*读取数据结束,引脚改为输出模式*/
- AM2311_GPIO_Init1();
- PBout(7)=1;
- if(AM2311_Data->check_sum ==AM2311_Data->humi_int + AM2311_Data->humi_deci + AM2311_Data->temp_int+ AM2311_Data->temp_deci)
- //核对校验位是否正确
- {
- // printf("返回的数据为1");
- return 1;
-
- }
-
- else
- {
- // printf("返回数据失败");
- return 0;
-
- }
-
-
- }
- else
- {
- // printf("YES\n");
- return 0;
- }
-
- }
复制代码- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include <string.h>
- #include "timer.h"
- #include "am2311.h"
- #include <stdio.h>
- #include "stm32f10x.h"
- //#include <stm32f1xx_hal.h>
- //在int之前定义,代表是整个工程中的变量,定义在某个函数当中,只能是在该函数内部进行使用,无法扩展extern
- u8 n=0;
- u8 m=0;
- u8 len=0;
- u16 Send_Time=0; //发送次数
- int RH_Value=0;
- int RH_H,RH_L=0;
- int TEMP_Value=0;
- int TP_H,TP_L=0;
- extern AM2311_Data_TypeDef AM2311_Data;
- extern u8 receive[20];//用于接受传输过来的数组
- int main(void)
-
- {
- u8 keysign=0; //按键标志
- u16 head=0x55aa; //发送变量
- u16 tail=0xaa55;
- u8 id_code[32]="174eec111de24bfaa1f3a8b12279dcd4"; //设备识别号
- u8 heart=0xff;
- u8 i=0;
- u8 sign_1s=0;
- u32 count_1s=0;
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
- LED_Init(); //LED端口初始化
- TIM4_Int_Init(99,7199); //1ms
- AM2311_GPIO_Init();
-
- // while(sign==0)
- while(1)
- {
- /*
- // if(Send_Time>=7) break;
- // delay_ms(2000);
- // if((USART_RX_STA&0x8000||Send_Time==0)&&(Send_Time<=7))//接收完成,对数据的内容进行判断。
- // {
- // if(Send_Time<=7)
- // Send_Time++;
- // switch(Send_Time)
- // {
- // case 1:printf("\r\nAT+CWMODE=3\r\n"); break; //printf("\r\nAT+CWMODE=1\r\n");//station模式,连入WiFi
- // case 2:printf("\r\nAT+RST\r\n"); break; //设置模式后,重启有效
- // case 3:printf("\r\nAT+CWJAP=\"ywx123\",\"87654321\"\r\n"); break;//Smart_Home_hbkj 11111111
- // case 4:printf("\r\nAT+CIPMUX=0\r\n"); break; //2350,2347 //单通道模式
- // case 5:printf("\r\nAT+CIPSTART=\"TCP\",\"39.96.179.213\",2347\r\n"); break; //连入的ip和端口号
- // //case 5:printf("\r\nAT+CIPSTART=\"TCP\",\"192.168.31.119\",1234\r\n"); break; //连入的ip和端口号
- // case 6:printf("\r\nAT+CIPMODE=1\r\n"); break; //透传模式
- // case 7:printf("\r\nAT+CIPSEND\r\n"); break; //开始发送数据
- // case 8 :break;
- // }
- //
- // if(Send_Time%2==0) //每改变一个连接状态,led灯状态改变一次
- // GPIO_ResetBits(GPIOC,GPIO_Pin_13);
- // else
- // GPIO_SetBits(GPIOC,GPIO_Pin_13 );//否则保持为同一个状态
- // while(1)
- // {
- // delay_ms(3000);
- // strflag1 = strstr(USART_RX_BUF,str1); //判断是否含有ready,如果有,则为1,否则为0
- // strflag2 = strstr(USART_RX_BUF,str2); //判断是否含有OK
- // if(Send_Time==7)
- // {
- // for(n=0;n<3;n++)//输出3次数据进行检查
- // {
- // printf("175240");
- // delay_ms(1000);
- // len=USART_RX_STA&0x3fff;//取出u16中的低16 位,得到此次接收到的数据长度
- // if(USART_RX_STA&0x8000)//判断接收数组的最高位是否为一,本次接收是否完成如果接受完成,就执行下列操作。
- // {
- // //if(USART_RX_BUF[1]=='h')
- // for(m=0;m<len;m++)
- // {
- // USART1->DR=USART_RX_BUF[m];//把每一个数据都在串口打印出来
- // while((USART1->SR&0X40)==0);//等待发送结束
- // }
- // }
- // }
- // sign=1;//
- // }
- // if(strflag1!=NULL||strflag2!=NULL|Send_Time==2)
- // {//两个只要有一个不为空就说明是 有上面两个值
- // memset(USART_RX_BUF,NULL,sizeof(USART_RX_BUF));//清空接收数组
- // USART_RX_STA=0x8000;//最高位强制为1、其他位不变、说明这次接收的数据中有OK和ready
- // break;//强行之一之后就进入串口中断。
- // }
- // }
- // }//执行完数据接收
- */
- //计算出实际湿度值的10倍
- if(Read_AM2311(&AM2311_Data)==1)
- {
- RH_Value= AM2311_Data.humi_int*256 + AM2311_Data.humi_deci;
- RH_H = RH_Value/10;
- RH_L =(RH_Value%10);
- //?????????10?
- TEMP_Value = AM2311_Data.temp_int*256 + AM2311_Data.temp_deci;
- TP_H = TEMP_Value/10;
- TP_L = TEMP_Value%10;
-
- printf("RH_Value=%d,RH_H=%d,RH_L=%d\r\n",RH_Value,RH_H,RH_L);
- delay_ms(1000);
- printf("TEMP_Value=%d,TP_H=%d,TP_L=%d\r\n",TEMP_Value,TP_H,TP_L);
- delay_ms(1000);
- delay_ms(1000);
- }
- }
-
- }
复制代码
所有资料51hei提供下载:
STM32F1 AM2311 单总线.7z
(192.03 KB, 下载次数: 32)
|