STM32 串口简介
串口作为单片机最重要的外部接口之一,同时又是我们嵌入式开发过程中重要的调试手段之一,其重要性不言而喻。几乎所有的单片机都有串口,STM32 也不例外。STM32 的串口资源相当丰富,功能也相当强劲,我所使用的原子哥的 STM32mini 开发板(STM32F103RCT6),最多可提供 5 路串口。
今天的实验
- 实现的功能
每隔一秒向电脑发送不同字符串
将接收到从电脑发送来的数据返回给电脑
- 实验材料
STM32mini 开发板
串口调试助手(Windows),minicom(Linux),超级终端(Windows)
开发工具:sw4stm32
首先新建工程
串口设置的一般步骤可以总结为如下几个步骤
串口时钟使能,GPIO 时钟使能
串口复位
GPIO 端口模式设置
串口参数初始化
开启中断并且初始化 NVIC
使能串口
编写中断处理函数
驱动代码:
usart.h
#ifndef __USART_H__ #define __USART_H__ #include <stm32f10x.h> #include <sys/_stdint.h> void USART_INIT(u32 bound); void USART_SendChar(USART_TypeDef* USARTx, uint8_t data); void USART_SendStr(USART_TypeDef* USARTx, char *str); #endif
usart.c
#include "usart.h" #include <misc.h> #include <stm32f10x_gpio.h> #include <stm32f10x_rcc.h> #include <stm32f10x_usart.h> //可以使用printf()函数输出 int __io_putchar(int ch) { USART_SendChar(USART1, ch); return ch; } // 发送单个字符 void USART_SendChar(USART_TypeDef* USARTx, uint8_t data){ USART_SendData(USARTx, data); // 操作USART_DR寄存器发送单个数据 while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);//等待发送寄存器TDR为空,为空时则置1 } //发送字符串函数,支持汉字,编码支持UTF-8 void USART_SendStr(USART_TypeDef* USARTx, char *str){ uint8_t i = 0; do { USART_SendChar(USARTx, *(str+i)); i++; }while(*(str+i) != '\0'); while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);//等待发送完成 } //初始化串口1 void USART_INIT(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitTypeDef; USART_InitTypeDef USART_InitTypeDef; NVIC_InitTypeDef NVIC_InitTypeDef; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA , ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitTypeDef.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitTypeDef.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitTypeDef.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitTypeDef); //初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitTypeDef.GPIO_Pin = GPIO_Pin_10; //PA10 GPIO_InitTypeDef.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitTypeDef); //初始化GPIOA.10 //Usart1 NVIC 配置 NVIC_InitTypeDef.NVIC_IRQChannel = USART1_IRQn; NVIC_InitTypeDef.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级3 NVIC_InitTypeDef.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitTypeDef.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitTypeDef); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitTypeDef.USART_BaudRate = bound; //串口波特率 USART_InitTypeDef.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 USART_InitTypeDef.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitTypeDef.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitTypeDef.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_InitTypeDef.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_Init(USART1, &USART_InitTypeDef); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断 USART_Cmd(USART1, ENABLE); //使能串口1 } void USART1_IRQHandler(void) {//串口1中断服务程序 // u8 Res; // Res = USART_ReceiveData(USART1); USART_SendData(USART1, (uint16_t) USART_ReceiveData(USART1));//将接收到的数据返回 }
main.c
#include <misc.h> #include <stdio.h> #include <stm32f10x.h> #include "delay/delay.h" #include "usart/usart.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wuninitialized" int main(int argc, char **argv) { delay_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 USART_INIT(115200); //串口初始化 char* msg; int i = 0; while (1) { sprintf(msg,"你好_欢迎来到_杨海健_博客__USART1_%d\r\n",i++); //sprintf(msg,"TAKE_TODAY_USART1_%d\r\n",i++); USART_SendStr(USART1,msg); delay_ms(1000); } } #pragma GCC diagnostic pop
实验结果
ON Linux
ON Windows
超级终端:
串口调试助手:
以下是去掉发送的程序执行结果,电脑发送没有出错
最后发送 LOGO
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于