串口是学习单片机重要的一项,用来显现数据和一些简略的操控指令十分便利,经过笔者这几天的测验,总结出了一些需求留意的当地:(以下代码悉数根据单片机STM32F407完成)
1、关于发送
除非你勾选了串口调试东西里边的HXE(16进制),不然串口发送的是对应字符的ASCII码,也就是说接纳的是每一位都是一个字节的ASCII码。比如说经过串口发送内容:adc123,其实发送的它们对应的ASCII码:61H 62H 63H 31H 32H 33H(H表明16进制)。假如发送勾选了“发送新行”,就会在发送的内容后边增加0DH 0AH(换行符),增加了两个字节。
在单片机编程中,假如用指针界说了一个无变量名的字符串:char *str=”abc123”;体系会主动在该变量后边增加一个‘\0’表明字符串的完毕,这样改字符串共占了7个字节。根据这个原因,发送字符串时能够选用下函数完成:
void usartSendString(u8 *str)
{
while(*str != 0)
{
while((USART3->SR&0x40)==0); //等候发送缓冲器空
USART_SendData(USART3,*str); //发送字符
str++;
}
而不是选用大多数选用的函数:
void uart3SendChars(u8 *str, u16 strlen)
{
u16 k= 0 ;
do {uart3SendChar(*(str + k)); k++; }
while (k < strlen);
}
比较以上两个函数,能够发现第一个函数进口参数少了要发送字符串的字长,第一个函数能够完成主动核算字长。当然,第一个函数仅能完成对字符串的发送,并不能完成对数组的发送。
2、关于接纳
信任大多数人都曾想完成将串口接纳的内容在LCD上显现,一个十分简洁的方法就是在串口接纳中止中直接将接纳到的字符显现在LCD上,可是因为改写LCD需求较长的时刻,在发送了一长串字符串后,很简单因为改写LCD需求较长的时刻而导致接纳到的内容不全。笔者想出了一个比较奇妙的函数,能够处理这样的烦恼:
#define USART3_REC_NUM 100 //界说最大接纳字节数
u8 receive_str[USART3_REC_NUM] = {0}; //接纳缓存数组
u16 uart_byte_count=0; //接纳的字节数
//串口中止函数
void USART3_IRQHandler(void)
{
u8 rec_data;
if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET)
{
rec_data=(u8)USART_ReceiveData(USART3); //接纳内容
receive_str[uart_byte_count]=rec_data;//将接纳到的内容存放在数组中
uart_byte_count++; //接纳的字节数+1
}
}
//将串口接纳到的数据复制出来,复制出来的字符串结尾保留了换行符'\x0d' '\x0a'
u8 USART_Receive2Str(u8 *str)
{
u16 i;
if(receive_str[uart_byte_count-1]== 0x0a) //接纳到换行符
{
for(i=0;i
{
*(str+i) =receive_str; //将数据复制出来
receive_str=0; //将接纳缓冲数组清零
}
uart_byte_count=0;
return 1; //成功复制到数据
}
else return 0; //复制数据失利
}
这样就将数组中的内容复制到其他数组中,进行相应的处理。可是要特别留意的是,要想运用以上函数,必须在串口调试东西中勾选“发送新行”才干完成,而且复制出来的字符串结尾保留了换行符'\x0d' '\x0a'。要想完成操控,能够运用下列方法:
u8 str[20]; //最多能复制出来20个字符
if(USART_Receive2Str(str) == 1)
{
if(strcmp("Light_led1\x0d\x0a",(char*)str)==0) LED1=0;//点亮LED1
elseif(strcmp("Close_led1\x0d\x0a",(char *)str)==0) LED1=1;//封闭LED1
elseif(strcmp("Open_beep\x0d\x0a ",(char *)str)==0)BEEP=1; //翻开蜂鸣器
elseif(strcmp("Close_beep\x0d\x0a ",(char *)str)==0)BEEP=0;//封闭蜂鸣器
//运用完后必定要将数组清零,便利下一次运用
u8 i=0;
while(*(str+i) !=0) /
{
*(str+i) = 0;
i++;
}
i=0;
}
以下代码完成经过开发板STM32F407完成对WIFI模块8266的操控,每按一次按键就发送一条指令,并将模块回来的信息显现到LCD上:
//操控指令,结尾的\x0d\x0a必定要加上,不然8266不能辨认指令,相当于勾选了“发送新行”
char *Ins1 = "AT+RST\x0d\x0a";
char *Ins2 = "AT+CWMODE=1\x0d\x0a";
char *Ins3 = "AT+CWLAP\x0d\x0a";
char *Ins4 ="AT+CWJAP=\"DLUTv0\",\"bugaosuniaaa\"\x0d\x0a";
char *Ins5 ="AT+CIPSTART=\"TCP\",\"192.168.5.98\",8080\x0d\x0a";
if(get_key_msg(&keymsg) == 1) //取得按键音讯
{
static u8 i=0;
if((keymsg.key == KEY0)&& (keymsg.status == KEY_DOWN))
{
switch(i)
{
case 0:uart3SendString((u8*)Ins1);i=1;LCD_DisplayString(10,10,16,"SendIns1");break;
case 1:uart3SendString((u8*)Ins2);i=2;LCD_DisplayString(10,10,16,"SendIns2");break;
case 2:uart3SendString((u8*)Ins3);i=3;LCD_DisplayString(10,10,16,"SendIns3");break;
case 3:uart3SendString((u8*)Ins4);i=4;LCD_DisplayString(10,10,16,"SendIns4");break;
case 4:uart3SendString((u8*)Ins5);i=0;LCD_DisplayString(10,10,16,"SendFinished");break;
default: break;
}
}
}
if(USART_Receive2Str(string) ==1)//将模块回来的内容显现在LCD上
{
u8 i=0;
LCD_DisplayString(1,yc,12,string);
yc+=12;
if(yc>=320){LCD_Clear(WHITE);yc=50;}
while(*(str+i) !=0)
{
*(str+i) = 0;
i++;
}
i=0;
}