许多传感器的使用方法是:单片机给传感器发送一帧数据,然后传感器返回单片机一帧有用数据,所以串口的收发功能十分重要。
时钟和下载方式就不讲了
串口配置,因为要接收数据,所以通常打开串口中断
注意要选到模块需要的波特率,数据位,校验位,停止位,很多模块的波特率是9600,不是我们常用的115200不一样。
打开中断:
串口配置就这些
发送函数:
HAL_UART_Transmit_IT(&huart1, (uint8_t *)CO2AskBuffer, sizeof(CO2AskBuffer));
其中第一个参数是串口号,第二个参数是要发送的数据起始地址,第三个是要发送的数据长度,一般都用sizeof函数专业一点。
把要发送的数据放在一个数组里:
uint8_t CO2AskBuffer[9]={0xFF,0x01,0x03,0x02,0x00,0x00,0x00,0x00,0xFB};
首先需要打开中断,通常是在单片机发送完指令后开中断:
uint8_t RecieveBuffer[1]={0};//暂存接收到的字符
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);
不定长接收:
uint8_t CO2Buffer[12];//收到的数据存放处
uint8_t RxLine=0; //记录接收数据长度
uint8_t errorBuffer[]="\r\nerror\r\n"; //错误提示
/**
* @brief 不定长数据接收
* @param 串口号
* @retval void
* @author smart_mode
* @Time 2021年11月21日
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
RxLine++;
CO2Buffer[RxLine-1]=RecieveBuffer[0];
if (RxLine>12) //根据自己的需要修改,当数据接收超多多少位就错了
{
RxLine=0;
memset(CO2Buffer,0,sizeof(CO2Buffer));
HAL_UART_Transmit_IT(&huart1, (uint8_t *)errorBuffer,sizeof(errorBuffer));
}
if (RecieveBuffer[0]==0x0A) //数据最后一字节,根据实际情况修改
{
HAL_UART_Transmit_IT(&huart1, (uint8_t *)CO2Buffer,RxLine); //如果接收到的数据都对,就将数据发送出去
RxLine=0;
}
RecieveBuffer[0]=0;
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);
//一定记得再次打开中断
}
我们可能需要判断传感器发送来的数据是否是正确的,也可能需要对数据帧的某几个字节做处理,这种情况可以用状态机的写法:
uint8_t NH3Buffer[10]; //存放模块返回的数据 16进制
uint8_t RxLine=0; //接收到的数据长度
uint8_t RecieveBuffer[1]={0};//临时存放数据
uint8_t gaozijie; //有用数据高字节
uint8_t dizijie; //有用数低字节
uint16_t NH3concentration;
double NH3Dec; //十进制的NH3浓度
uint8_t errorBuffer[]="\r\nerror\r\n";
extern uint8_t flag;
/**
* @brief 接收回调:保存数据并处理
* @param 串口号
* @retval void
* @author smart_mode
* @Time 2021年11月21日
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
RxLine++; //接收到的数据加一
NH3Buffer[RxLine-1]=RecieveBuffer[0]; //保存收到的正确数据
//判断帧头是否正确,只要某一位错了,就重新等待正确的第一位数据
if (RxLine==1)
{
if(RecieveBuffer[0]==0xFF)
{
RxLine=1;
}
else
{
RxLine=0;
}
}
else if(RxLine==2)
{
if(RecieveBuffer[0]==0x01)
{
RxLine=2;
}
else
{
RxLine=0;
}
}
else if(RxLine==3)
{
if(RecieveBuffer[0]==0x07)
{
RxLine=3;
}
else
{
RxLine=0;
}
}
else if(RxLine==4)
{
if(RecieveBuffer[0]==0x02) //分辨率0.01
{
RxLine=4;
}
else
{
RxLine=0;
}
}
else if(RxLine==5)
{
gaozijie=RecieveBuffer[0]; //保存有用数据高字节
}
else if(RxLine==6)
{
dizijie=RecieveBuffer[0]; //保存有用数据低字节
//16进制转换10进制,并缩小100倍
NH3Dec=gaozijie*256+dizijie*1;
NH3Dec=NH3Dec*0.01;
}
else if(RxLine==7)
{
if(RecieveBuffer[0]==0x00)
{
RxLine=7;
}
else
{
RxLine=0;
}
}
else if(RxLine==8)
{
if(RecieveBuffer[0]==0x00)
{
RxLine=8;
}
else
{
RxLine=0;
}
}
else if(RxLine==9)
{
if(RecieveBuffer[0]==0x00)
{
RxLine=9;
}
else
{
RxLine=0;
}
}
else if(RxLine==10&flag==0)
{
printf("%.2f ppm",NH3Dec);
flag=1;
RxLine=0;
}
else
{
flag=1;
RxLine=0;
}
RecieveBuffer[0]=0;
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);
}
CO2和NH3和HCHO(二氧化碳和氨气和甲醛)的检测代码已上传我的资源,需要可自行下载
PS 二氧化碳是环境中有的气体,比较容易检测。空气中的氨气几乎没有,得去卫生间这种地方收集,可以用排水集气法。甲醛可以去新装修的房子里收集,如果没有这个条件可以使用酒精棉,一些酒精棉里面有甲醛。