51单片机应用开发(进阶)---串口接收字符命令
实现目标
1、巩固UART知识;
2、掌握串口接收字符数据;
3、具体实现目标:(1)上位机串口助手发送多字符命令,单片机接收命令作相应的处理(如:openled1 即打开LED1;closeled1 即关闭LED1;)
一、主要知识点
1.1 字符串定义
字符串是由字母、数字、下划线和空格等各种字符组成的一串字符,是一个常量。由一对双引号括起来。字符串的末尾都默认有一个'\0'的结束符。
C语言存储字符,其实是存储字符所对应的ASCII码,因此字符可以以%c或者%d输出均可以,需要作为常识记住的是:字符'0'对应的ASCII码为48,字符'A'对应的ASCII码为65,字符'Z'对应的ASCII码为90,字符'a'对应的ASCII码为97,字符'z'对应的ASCII码为122; 字符类型char占用1个字节。
用来存放字符的数组称为字符数组,字符数组实际上是一系列字符的集合,也就是字符串,C语言通常有两种表示字符串的方法:
第一种:定义一个字符数组;char str[]="abcd";
第二种:字符串指针; const char * str="hello"; 这种方式不可通过对字符指针解引用进行修改字符串,因为字符串常量不可修改!
这二者都是使用字符串常量对其进行初始化,从指针角度理解,本质一样,不论是字符数组,还是字符指针,str都代表字符串首字符的起始地址。区别在于:字符数组名为常量,常量不可以作左值!字符指针是变量,但是字符指针不可以进行解引用再修改值。
获取字符串的长度
方法一:sizeof()运算符
方法二:strlen()函数
求字符串“abcd”的长度
int str[]={"abcd"}
int len1=sizeof(str)/sizeof(str[0);
int len2=strlen(str);
解析:结果len1=5;len2=4;
sizeof 和strlen总结
①sizeof是运算符;strlen是库函数,包含在string.h头文件中
②sizeof功能是获得所建立对象的字节大小;strlen函数是获得字符串所占内存的有效字节数;
③sizeof运算符的参数可以是数组、指针、对象、函数等;strlen函数的参数必须是以'\0'结尾的字符串的指针;
④sizeof运算符计算大小在编译时就完成,因此不能用来计算动态分配内存大小;strlen函数结果要在运行时才能计算出来。
1.2 strstr 函数应用
(1) 头文件
#include <string.h>
(2) 函数原型
char *strstr(const char *haystack, const char *needle);
(3) 函数作用
1、strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL。
情景一:
用于单次匹配
返回的是匹配成功的字符串以及后面的字符串
#include <stdio.h>
#include <string.h>
main()
{
char *s="GoldenGlobalView";
char *l="lob";
char *p;
p=strstr(s,l);
if(p)
printf("%s",p);
else
printf("NotFound!");
return 0;
}
二、原理图设计
STC89C52RC/RD+系列单片机串行口对应的硬件部分对应的管脚是P3.0/RxD和P3.1/TxD。
三、程序设计
3.1单片机接收上位机PC的命令
参数:波特率9600 ;SMOD为0,波特率不加倍;定时器1,工作模式2,8位自动重装。
具体功能:发字符 a,开启LED1; 发字符 b,关闭LED1;
#include <REGX52.H>
#define FOSC 11059200L //System frequency
#define BAUD 9600 //UART baudrate
sbit LED1 = P2^0;
int cmd = 0;//命令
bit flag = 0;
void Uart_send(unsigned char dat);
void Uart_send_str(unsigned char *p);
void Delay500ms();
void main()
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8-bit variable UART
TMOD = 0x20;//0010 0000 //Set Timer1 as 8-bit auto reload mode
TH1 = TL1 = -(FOSC/12/32/BAUD); //Set auto-reload vaule
TR1 = 1; //Timer1 start run
ES = 1; //Enable UART interrupt
EA = 1; //Open master interrupt switch
while(1)
{
if(flag == 1)//查询是否接收一字节的命令
{
flag = 0;//标志位清零0
if(cmd == 'a')
{
LED1 = 0;
Uart_send(cmd);
}
else if(cmd == 'b')
{
LED1 = 1;
Uart_send(cmd);
}
}
}
}
void Uart_send(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
void Uart_send_str(unsigned char *p)
{
while(*p!='\0')
{
Uart_send(*p);
p++;
}
}
void Uart_Isr() interrupt 4
{
if (RI == 1)
{
RI = 0; //Clear receive interrupt flag
flag = 1;
cmd = SBUF;
}
}
void Delay500ms()//@11.0592MHz
{
unsigned char i, j, k;
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
3.2 字符串命令控制LED
具体功能:发字符串open,开启LED1; 发字符串close,关闭LED1;
#include <REGX52.H>
#include <stdio.h>
#include <string.h>
#define FOSC 11059200L //System frequency
#define BAUD 9600 //UART baudrate
sbit LED1 = P2^0;
typedef struct
{
unsigned char buff[32]; //用于存放接收到的字符串
unsigned char flag; //接收完成中断标志位
unsigned char len; //用于偏移字符串指针,可以理解为长度,如果buff设得很长,对应这里需要改成u16
}REC;
REC UART_rec={0}; //初始化结构体
const char *substr1 = "open";
const char *substr2 = "close";
void Uart_send(unsigned char dat);
void Uart_send_str(unsigned char *p);
void Delay500ms();
void main()
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8-bit variable UART
TMOD = 0x20;//0010 0000 //Set Timer1 as 8-bit auto reload mode
TH1 = TL1 = -(FOSC/12/32/BAUD); //Set auto-reload vaule
TR1 = 1; //Timer1 start run
ES = 1; //Enable UART interrupt
TI = 1;
EA = 1; //Open master interrupt switch
while(1)
{
if(UART_rec.flag == 1)//若接收完成
{
if (strstr(UART_rec.buff,substr1)!= NULL)
{
printf("开启LED1\n");
LED1 = 0;
}
else if(strstr(UART_rec.buff,substr2)!= NULL)
{
printf("关闭LED1\n");
LED1 =1;
}
// printf("接收到了:%s\r\n",UART_rec.buff);
UART_rec.flag = 0; //接收标志位清零,准备接收下一字符串
}
}
}
void Uart_send(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
void Uart_send_str(unsigned char *p)
{
while(*p!='\0')
{
Uart_send(*p);
p++;
}
}
void Uart_Isr() interrupt 4
{
unsigned char temp = 0;
if (RI == 1)
{
RI = 0; //清除接收中断标志
temp = SBUF;
if(temp=='\r'||temp=='\n'||UART_rec.len >= 32)
{
UART_rec.buff[UART_rec.len]='\0';
UART_rec.flag = 1 ;//数据包接收完成标志
UART_rec.len=0; //为下一个数据包做准备
}
else
{
UART_rec.buff[UART_rec.len++] = temp;
}
}
}
void Delay500ms()//@11.0592MHz
{
unsigned char i, j, k;
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
四、实验效果
五、仿真实现
5.1单片机接收的字符命令仿真
总结
原文地址:https://blog.csdn.net/luojuan198780/article/details/144193293
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!