串口通信操作STM32f4单片机LED 蜂鸣器(io)

串口通信操作STM32f4单片机LED 蜂鸣器(io)

首先将串口与PC通信

单片机中串口1需要连接p6 中的PA9连接rxd PA10连接txd并使能相应io,io模式为挽推复用,复用为串口USART1(单片机串口1使用usb-串口与pc连接)。
串口通信操作STM32f4单片机LED 蜂鸣器(io)
在对串口和io初始化后,我们要对串口进行中断设置和优先级设置以便于我们处理串口发送的数据。
HAL_NVIC_EnableIRQ(USART1_IRQn); //使能 USART1中断通道
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级 3,子优先级 3
下面开启中断,其参数含义为串口句柄,数据缓冲区指针,数据量。
HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);
HAL库中有通用的中断处理函数,存在的意义是方便移植,他本身并不是中断函数的实现。
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
这个函数进行了一些串口连接超时处理,而在其中HAL_UART_IRQHandler(&UART1_Handler);
此函数判断串口状态以及所属平台等(部分判断意义我不明)
状态正常则执行中断函数的实现HAL_UART_RxCpltCallback(huart);
一般的HAL库的中断处理函数只有上述一个入口,实现代码为
串口通信操作STM32f4单片机LED 蜂鸣器(io)
其中USART_RX_STA是接收标识,初值为0每接收一个缓存RxXferSize(我们设置为1字节)就加一,通过和0x8000做位于运算可以得知最高位是否为1,为1则说明接收完毕。接收的数据我们定义了一个u8(无符号char形)数组u8 USART_RX_BUF[USART_REC_LEN];来存储其中USART_REC_LEN=200.
以上串口调用部分就完成了
在主函数中直接使用printf语句就能将数据从单片机上发到pc上位机中。效果如图(qt学习中有做过一个简单的pc串口上位机)
串口通信操作STM32f4单片机LED 蜂鸣器(io)
那么pc能不能通过给单片机发送某个特定的数据来操作单片机的io呢?
当然是可以的。
思路与起调串口io一致,在串口中断函数中可以使用strcmp函数(两字符串相等返回0)直接与从串口接收到的数据对比,若发送了设置好的字符如:打开LED 则操作相应io。
查单片机使用手册可知灯 DS0 DS1 和蜂鸣器分别对应PF9 PF10 PF8,都是上拉生效可以一起定义初始化。
HAL库直接提供了函数HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);
在初始化后直接可以操作,其中GPIO_PIN_RESET为拉低GPIO_PIN_SET为拉高。
还有一种方式是使用带位操作来实现,相比于hal库更加灵活,通过io地址映射来实现,列如点亮灯DS0
PFout(9)=1;即可
PFout函数中封装BIT_ADDR(GPIOF_ODR_Addr,n)函数addr对应参数1,n对应参数2
(addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2) 带位操作地址计算。以上完成了对LED灯和蜂鸣器的操作。
那么接下来直接将pc通过串口发送的数据进行对比选择拉高/拉低哪个io即可。
但实际操作中 我发现直接使用指针访问USART_RX_BUF(保存串口接收数据的数组)出现乱码,原因未知。改用循环遍历将数组元素取出成功。主要代码如下:

串口通信操作STM32f4单片机LED 蜂鸣器(io)
由于验证无法通过图片表示这里不贴图了。下附录源代码