单片机
返回首页

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)!='');


    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));

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 光控音效发生器电路

  • 基于IC555的可变PWM振荡器电路

  • 如何使用LED驱动器LM3915制作振动计

  • 一个简单的立体声平衡指示器电路

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章