需求: pc端使用串口发送字符串控制开发板led

解决方案:  使用串口接受中断搭配空闲中断来实现。

原理:   串口发送字符串到开发板,开发板触发接受中断,由于串口一次只能发送一个字节,所以会多次进入接受中断,直到接受完所有字符,接受完之后就会触发空闲中断,在空闲中断里判断从接受中断获取到的字符串再进行相应的处理。

坑1: 

对于此方案而言,接受中断中不能使用打印函数,因为打印函数会消耗时间,接受中断相当于被打断了一下。然后会被系统认定为空闲,就会出现只接受到一个字符然后就直接进空闲中断的情况。

坑2(也不算坑):

此问题我估计是开发板硬件设计的问题,在主函数的while(1)中一只点亮led4,然后串口中断服务函数中发送控制字符串,发送open就点亮led1,发送close就关闭led1,这时候就会出现有时能打开或者关闭led,有时又不可以。非常奇怪,后面经过多次调试发现,把主函数while(1)中的led4去掉就能完美运行,非常奇怪,我配置所有led初始化对寄存器的操作是完全没有影响到其他led的,最后总结只能是开发板led的供电问题。

 

 

核心代码如下:

#include "nvic.h"

u8 str[50] = {0};

void USART1_IRQHandler()

{

 static u8 i = 0;

 if(USART1->SR & (1<<5)) //判断是否为接收中断

 {

  str[i] = USART1->DR; //读DR可以清除中断标志位

  i++;

 }

 

 if(USART1->SR & (1<<4)) //判断是否为空闲中断

 {

  USART1->SR; //清除中断标志位

  USART1->DR;

  str[i]='\0';  //字符串需要\0结尾

  i = 0;   //i重置为了能重复接受

  printf("(空闲中断)接收到数据的长度为:%d\r\n",strlen((char *)str));

  printf("(空闲中断)开发板接收到的数据为:%s\r\n",str);

  if(strcmp("open",(char *)str) == 0)

  {

   GPIOC->ODR &= ~(1<<5);  //点亮led

  }

  else if(strcmp("close",(char *)str) == 0)

  {

   GPIOC->ODR |= (1<<5);   //关闭led

  }

 }

}

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐