USART——串口通讯
2022-03-15 来源:eefocus
开发平台
野火F429开发板
标准库
通讯基本概念
同步通讯和异步通讯
同步通讯和异步通讯的区别在于有没有时钟信号线
全双工、半双工、单工通讯
全双工可以收发同时进行
半双工可以收发但不可同时进行
单工只能收或发
USART
三大时序:USART、I2C、SPI,USART是其中之一了
USART时序:起始位为低电平、然后发送数据8位数据是没有校验位的,9位数据是有校验位的、停止位为高电平。时序如下图:(字长为8)
现在我使用串口一般都是打印调试信息或者蓝牙通讯 ,只会用到TX和RX,不需要用到时钟信号线,所以是异步半双工
如果想要操作寄存器,那就要看功能框图了
1.TX发送数据引脚、RX接受数据引脚,所以要把引脚配置为串口复用引脚(每个串口对应的引脚都不一样,这样查看手册)
2.发送数据寄存器和接收数据寄存器,还有发送移位寄存器和接受移位寄存器
发送数据时,发送寄存器将数据一位位的移向移位寄存器发送出去
接收数据时,将数据接收到移位寄存器然后再移向接收寄存器
3.控制寄存器CR1:要使能USART、设置数据位(字长)、是否开启校验位、奇校验还是偶校验、作为发送器还是作为接收器(使能)
4.波特率设置,直接操作寄存器的时候要自己算出数值,然后写入寄存器,如果用标准库就不需要计算了,已经算好了。公式如下:
OVER8:过采样模式,根据选择的模式去更改权位(计算小数的时候)
使用标准库的话上面的了解一下就好了
串口的四个参数:波特率、数据位、校验位、停止位。
波特率:每秒中传输了多少个码元
数据位:八位或者九位,八位是没有校验位九位是有校验位
使能了校验位之后每个字符的数据帧格式:启动位+数据位+校验位+停止位
没有使能校验位每个字符的数据帧格式:启动位+数据位+停止位
停止位:表示数据已经发送完成了,停止位长传输准确率高,效率低 停止位分为0.5位、1位、1.5位、2位
0.5位和1.5位用在智能卡模式,一般情况下用1位停止位,2位停止位一般用于USART模式、单线模式、调制解调器模式。
一般情况:波特率:115200、数据位:8位、无校验位、停止位:1位
要想实现通讯,发送设备和接受设备波特率、数据位、校验位、停止位必须相同才可实现通讯
1.初始化串口的引脚
2.配置串口的参数
3.编写发送字符串函数
4.重定向printf函数和scanf函数
什么是重定向?简单来说,你喝水要喝进肚子里,可是你喝的时候是喝进脑子里的,你必须重定向才能让水喝进肚子里。
代码如下:
#ifndef __USART__H
#define __USART__H
#include 'main.h'
#define USART_TX_CLOCK RCC_AHB1Periph_GPIOA
#define USART_RX_CLOCK RCC_AHB1Periph_GPIOA
#define USART_TX_PORT GPIOA
#define USART_RX_PORT GPIOA
#define USART_TX_PINSOURCE GPIO_PinSource9
#define USART_RX_PINSOURCE GPIO_PinSource10
#define USART_AF GPIO_AF_USART1
#define USART_TX_PIN GPIO_Pin_9
#define USART_RX_PIN GPIO_Pin_10
#define USART_CLOCK_Cmd() RCC_APB2PeriphClockCmd(USART_CLOCK,ENABLE)
#define USART_CLOCK RCC_APB2Periph_USART1
#define USART USART1
#define BAUDRATE 115200
void USART_GPIO_Config(void);
void USART_Config(void);
void USATR_Sendbyte(uint16_t data);
void USART_Sendstring(char *string);
int fputc(int ch, FILE *f);
#endif
#include 'usart.h'
void USART_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*开USART引脚复用时钟*/
RCC_AHB1PeriphClockCmd(USART_TX_CLOCK|
USART_RX_CLOCK,ENABLE);
/*
**复用模式
**不上拉不下拉
**TX->PB6 RX->PB7
*/
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Pin=USART_TX_PIN;
GPIO_Init(USART_TX_PORT,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Pin=USART_RX_PIN;
GPIO_Init(USART_RX_PORT,&GPIO_InitStruct);
/*设置复用功能*/
GPIO_PinAFConfig(USART_TX_PORT,USART_TX_PINSOURCE,USART_AF);
GPIO_PinAFConfig(USART_RX_PORT,USART_RX_PINSOURCE,USART_AF);
}
void USART_Config(void)
{
USART_InitTypeDef USART_InitStruct;
/*引脚配置*/
USART_GPIO_Config();
/*开串口时钟*/
USART_CLOCK_Cmd();
/*
**波特率115200
**发送和接收模式
**无校验位
**停止位为1
**8位数据位
**不使用硬件流
*/
USART_InitStruct.USART_BaudRate=BAUDRATE;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART,&USART_InitStruct);
/*使能串口*/
USART_Cmd(USART,ENABLE);
}
void USATR_Sendbyte(uint16_t data)
{
USART_SendData(USART,data);
while(USART_GetFlagStatus(USART,USART_FLAG_TXE)==RESET);
}
void USART_Sendstring(char *string)
{
unsigned int i=0;
do
{
USATR_Sendbyte(*(string+i));
i++;
} while (*(string+i)!='