串口通信USART----STM32最小系统板
/ 波特率115200。
串口通信:ASCII码适用于传输文本数据,而十六进制适用于传输二进制数据。选择哪种数据传输方式取决于具体的应用场景和需求。
有三个串口 UART1 UART2 UART3
波特率:每秒钟最多传输几位;常用的波特率:9600、115200、921600
波特率寄存器BRR


怎么知道串口是哪个引脚-------读表
在左侧种pins下面有各种各样的封装,我们使用的是LQFP48,关注LQFP


这是没有使能重映射的时候TX对应PA9,RX对应PA10。PA9接RX,PA10接TX

这是使能重映射后的TX和RX

TX为PB6,RX为PB7。PB6接RX,PB7接TX
又一个问题?怎么看模式和最大输出速度
IO配置表


RX最好不要选择浮空输入,避免外界干扰,选择上拉模式,在没有数据的时候默认高电平。
为什么使用上拉,不使用下拉,这就跟USART的传输模式有关,空闲位都是高电平

配置完成

若使用重映射

再此之前,完成外设的配置后,接下来实现串口发送数据
几个标志位
TxE和TC标志位 TXE监控是否能写入发送寄存器,TC监控是否完成
USART_FLAG_RXNE |
接收数据寄存器(RDR)非空,已收到数据。 | 检查是否有数据可读取。 |


此时,USART1 和 USART2 本质上是 指向各自寄存器组起始地址的结构体指针。
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
传参类型定义为指针,后面调用的时候用,My_USART_SendBytes(USART1就行)
//串口名;发送数据;字节数量
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size) {
for(uint32_t i = 0; i < Size; i++) {
// 1. 等待发送寄存器空(可写入新数据)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 2. 写入数据到发送寄存器
USART_SendData(USARTx, pData[i]);
}
// 3. 等待所有数据完全发送(包括移位寄存器)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
注解: 当不为空的时候,一直重复while的死循环,为空的时候,才执行2.

#include "stm32f10x.h"
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size);//声明
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//串口引脚的初始化
GPIO_InitTypeDef GPIO_InitStruct = {0};//**变量+变量名**
//TX
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//RX
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStruct);
USART_InitTypeDef USART_InitStruct={0};
USART_InitStruct.USART_BaudRate = 115200; // 波特率115200
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 8位数据
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 1位停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 双向通
USART_Init(USART1, &USART_InitStruct); // 初始化USART1
USART_Cmd(USART1, ENABLE); // 启动USART1
uint8_t byteTosend[]={1,2,3,4,5};
My_USART_SendBytes(USART1,byteTosend,5);
while(1)
{
}
}
//串口名;发送数据;字节数量,发给电脑
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
for(uint32_t i = 0; i < Size; i++) {
// 1. 等待发送寄存器空(可写入新数据)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 2. 写入数据到发送寄存器
USART_SendData(USARTx, pData[i]);
}
// 3. 等待所有数据完全发送(包括移位寄存器)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
如果要打印字符串呢?
#include "stm32f10x.h"
#include<stdio.h>
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size);//声明发送函数
void My_USART_Init(void);
int fputc(int ch,FILE*f);
int main(void)
{
//测试发送数据
// uint8_t byteTosend[]={1,2,3,4,5};
// My_USART_SendBytes(USART1,byteTosend,5);
//测试打印字符串
My_USART_Init();
printf("Hello world.\r\n");
while(1);
}
//通过串口发送多个字节,程序下载到单片机里面,发送的是单片机往电脑发送
//串口名;发送数据;字节数量
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
for(uint32_t i = 0; i < Size; i++) {
// 1. 等待发送寄存器空(可写入新数据)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 2. 写入数据到发送寄存器
USART_SendData(USARTx, pData[i]);
}
// 3. 等待所有数据完全发送(包括移位寄存器)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
void My_USART_Init(void)//三部:时钟初始化,定义结构体变量,结构体变量赋值,初始化函数,开启串口函数
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//串口引脚的初始化
GPIO_InitTypeDef GPIO_InitStruct = {0};//**变量+变量名**
//TX PA9
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//RX PA10
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStruct={0};
USART_InitStruct.USART_BaudRate = 115200; // 波特率115200
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 8位数据
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 1位停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 双向通
USART_Init(USART1, &USART_InitStruct); // 初始化USART1
USART_Cmd(USART1, ENABLE); // 启动USART1
}
//FILE报错,头文件需要引用stdio.h
//如果需要 printf 支持(studio),不要修改 _fputc,而是重写 fputc。如果仅需底层串口发送,可以另写一个函数(如 USART_SendChar),但需手动调用。
//测试程序 printf("Hello world.\r\n");
//注意在魔法棒-target里面勾选Use MicroLIB;MicroLIB 是 ARM 公司提供的一个高度优化的简化版 C 标准库,专为资源受限的嵌入式系统设计.
// 实现 fputc(printf 依赖此函数)
int fputc(int ch, FILE *f) {
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, (uint8_t)ch);
return ch;
}
串口接收数据?
RXNE标志位------接收数据寄存器非空(receive data register not empty),非空的时候,RXNE=1
通过电脑串口控制小灯的亮灭
#include "stm32f10x.h"
#include<stdio.h>
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size);//声明发送函数
void My_USART_Init(void);
int fputc(int ch,FILE*f);
void My_OnBoardLED_Init(void);
int main(void)
{
My_USART_Init();
My_OnBoardLED_Init();//每次初始化函数不要漏掉了
//测试发送数据
// uint8_t byteTosend[]={1,2,3,4,5};
// My_USART_SendBytes(USART1,byteTosend,5);
//测试打印字符串
// My_USART_Init();
// printf("Hello world.\r\n");
// while(1);
//串口点亮led
while(1){
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
uint8_t btyeRcvd=USART_ReceiveData(USART1);
if(btyeRcvd=='0')//字符0//不加双引号也可以串口那边字符改为Hex就可以
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
else if(btyeRcvd=='1')
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
}
}
//通过串口发送多个字节,程序下载到单片机里面,发送的是单片机往电脑发送
//串口名;发送数据;字节数量
void My_USART_SendBytes(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
for(uint32_t i = 0; i < Size; i++) {
// 1. 等待发送寄存器空(可写入新数据)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
// 2. 写入数据到发送寄存器
USART_SendData(USARTx, pData[i]);
}
// 3. 等待所有数据完全发送(包括移位寄存器)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
void My_USART_Init(void)//三部:时钟初始化,定义结构体变量,结构体变量赋值,初始化函数,开启串口函数
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//串口引脚的初始化
GPIO_InitTypeDef GPIO_InitStruct = {0};//**变量+变量名**
//TX PA9
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//RX PA10
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStruct={0};
USART_InitStruct.USART_BaudRate = 115200; // 波特率115200
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 8位数据
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 1位停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 无校验
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 双向通
USART_Init(USART1, &USART_InitStruct); // 初始化USART1
USART_Cmd(USART1, ENABLE); // 启动USART1
}
//FILE报错,头文件需要引用stdio.h
//如果需要 printf 支持(studio),不要修改 _fputc,而是重写 fputc。如果仅需底层串口发送,可以另写一个函数(如 USART_SendChar),但需手动调用。
//测试程序 printf("Hello world.\r\n");
//注意在魔法棒-target里面勾选Use MicroLIB;MicroLIB 是 ARM 公司提供的一个高度优化的简化版 C 标准库,专为资源受限的嵌入式系统设计.
// 实现 fputc(printf 依赖此函数)
int fputc(int ch, FILE *f) {
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, (uint8_t)ch);
return ch;
}
void My_OnBoardLED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct={0};
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
GPIO_Init(GPIOC,&GPIO_InitStruct);
}
总结:三个标志位:
两个发送,一个接收
TXE TC RXNE
TXE (Transmit Data Register Empty)
-
含义:发送数据寄存器空-------空为1
TC (Transmission Complete)
-
含义:发送完成
-
触发条件:当发送移位寄存器为空且最后一个位已发送时置位----完成为1
RXNE (Receive Data Register Not Empty)
-
含义:接收数据寄存器非空
-
触发条件:当接收到数据并转移到接收数据寄存器时置位---非空为1
封装串口代码
后续要串口的代码,声明下#include“usart.h”
更多推荐



所有评论(0)