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
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于