USART——串口通讯

开发平台

  • 野火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)!='\0');

    while(USART_GetFlagStatus(USART,USART_FLAG_TC)==RESET);
}


///重定向c库函数printf到串口,重定向后可使用printf函数

int fputc(int data, FILE *f)
{
		/* 发送一个字节数据到串口 */
		USART_SendData(USART,(uint8_t) data);
		
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(USART, USART_FLAG_TXE) == RESET);		
	
		return (data);
}

int fgetc(FILE *f)
{
    /*等待接受完毕*/
    while(USART_GetFlagStatus(USART,USART_FLAG_RXNE)==RESET);

    return (USART_ReceiveData(USART));
}
发布了13 篇原创文章 · 获赞 19 · 访问量 1812

猜你喜欢

转载自blog.csdn.net/qq_44622367/article/details/103963842