51单片机 | UART | 接收数据 | 判定字符串接收完毕
实现思路:
每接收一个字符,重置定时器,若定时器达到设定值则判定为字符串完整接收。
实现过程:
定义一个变量记录空闲时间,
static unsigned char s_idle_count = 0;
现阶段思路:每毫秒加一,每收到一个字符置零。
定义定时器0回调:
void Dri_UART_Timer0Callback()
{
s_idle_count++;
}在初始化函数Dri_UART_Init中注册空闲检测函数:
Dri_Timer0_RegisterCallback(Dri_UART_Timer0Callback);
此时s_idle_count每毫秒加一。
每收到一个新字符,重新计时(重置s_idle_count),
在串口中断中重置:
void Dri_UART_Handler() interrupt 4
{
if(RI == 1) {
s_idle_count = 0;
RI = 0;
}
}判断:当s_idle_count > 10时处理逻辑,
定义数组用于接收SBUF:
static char idata s_buffer[16];
(最长16字符)
定义索引:
static unsigned char s_index;
修改串口中断逻辑,给s_buffer的索引位赋值并自增索引位:
void Dri_UART_Handler() interrupt 4
{
if(RI == 1) {
s_buffer[s_index++] = SBUF;
RI = 0;
}
}修改Dri_UART_Timer0Callback(),判断空闲时间大于十毫秒,同时数组应不为空(s_index不为0):
s_idle_count++;
if (s_index > 0 && s_idle_count >=10)
{
//数据处理逻辑
}需要ReceiveString方法,在main中重复调用ReceiveString函数,
如果字符串接收完毕,函数返回1,将s_buffer内容赋给字符串,否则返回0。
判断是否接收完毕,定义标志位并赋初始值:
static bit s_is_complete = 0;
完善空闲计时方法,一旦接收完毕,标志位置1,
void Dri_UART_Timer0Callback()
{
s_idle_count++;
if (s_index > 0 && s_idle_count >= 10)
{
s_is_complete = 1;
}
}定义方法,将s_buffer数组内容赋给str,
并将标志位和索引清零:
bit Dri_UART_ReceiveString(char *str)
{
if (s_is_complete == 1)
{
for (i = 0; i < s_index; i++)
{
str[i] = s_buffer[i];
}
s_is_complete = 0;
s_index = 0;
return 1;
}
return 0;
}在main.c中:
#include <STRING.H>
声明数组:
unsigned char idata str[16];
初始化定时器和串口:
Dri_Timer0_Init(); Dri_UART_Init();
(先初始化定时器以设置NULL,否则无法正常注册)
使用STRING.H的strcmp比较字符串:
strcmp(str,"on") == 0
main方法:
void main()
{
unsigned char idata str[16];
Dri_Timer0_Init();
Dri_UART_Init();
while(1)
{
if (Dri_UART_ReceiveString(str))
{
if (strcmp(str,"on"))
{
P00 = ~P00;
Dri_UART_SendString("LED1 IS ON");
} else if (strcmp(str,"off")) {
P01 = ~P01;
Dri_UART_SendString("LED2 IS ON");
} else {
Dri_UART_SendString("UNKNOWN COMMAND")
}
}
}
}此时应可以正常接收命令,但若上一条命令长于本条,则无法正确识别,
原因:
短命令无法完全覆写长命令,而strcmp检测"\0",故将无法检测正确内容
解决方式:
每次接受命令后后清空str[]数组
每次收到完整字符串,在最后一个字符后加"\0"
方式2的实现:
修改Dri_UART_ReceiveString方法,在for循环后于i位设'\0':
bit Dri_UART_ReceiveString(char *str)
{
if (s_is_complete == 1)
{
for (i = 0; i < s_index; i++)
{
str[i] = s_buffer[i];
}
str[i] = '\0';
s_is_complete = 0;
s_index = 0;
return 1;
}
return 0;
}
