UART串口通讯协议

硬件UART:

1.传输方式:

        串行传输,低位先行

2.传输类型:

        帧传输。有校验位则9位一帧,无校验位则8位一帧。

3.引脚数:2

        RX

        TX

4.波特率:

        一秒钟能传输的bit个数。

                波特率 = 外设时钟频率÷ 分频系数 ÷16。

                外设时钟是指外挂载总线APB1或APB2的时钟,两者频率不同。

                要÷16是因为在读取数据时,一位bit需要16个时钟采样,来防止/判断噪音。
所以÷16得到波特率,是为了保证系统时钟能够有足够快的频率,保证对每bit的传输都×16倍时间去检测,得到真正的一位bit发送接收时间。
不然假设16MHz的外设时钟,不分频得到波特率,那么实际一位的时间需要16*16Mhz的时钟才能正确发送,但这已经远远超出了外设时钟的上限(个人理解)(1MHz = 1 000 000  Hz)

5.停止位时间:

        发送一个字节数据(8bit)之后,停止位占多少个bit时钟周期(0.5,1,1.5,2),一般1个。(结构体初始化时配置)

6.字节长度:

        8位、9位。一般8位不加校验位,9位加校验位。

7.DR寄存器:

        内分   发送数据寄存器+发送移位寄存器接收寄存器+接收移位寄存器

                对软件代码而言,收发都是访问DR地址,不对其内部的地址进行细分。也就是一个地址两种功能,Rdata = DR就是接收;DR = Tdata就是发送。具体逻辑由硬件判断。

                发送流程:

                       ①调用函数判断发送数据移位寄存器是否空(标志位TXE—TE Empty空),判断数据有(1)没有(0)从发送数据寄存器被硬件自动转移到发送移位数据寄存器。

                       ②空的话则把数据发送给DR(赋值给DR :   DR = Tdata)。

                        ③为了下一次方便发送的话,可以在每次发送后等待TXE=1(即发送移位寄存器空),让下一次数据进来的时候不用等待,直接发送。

                接收流程:

                        ①调用函数判断接收数据寄存器是否非空(标志位TXNE — TX Not Empyt ),判断数据有(1)没有(0)从接收移位寄存器被硬件自动转移到接收数据寄存器

                        ②读取值为1(非空)的话,就要读取接收寄存器的数据(Rdata = DR)

                        ③在接收寄存器内数据时(RXNE == 1),对寄存器进行读取,会自动清除标志位

8空闲状态:

        TX高电平

9.启动与发送:

                启动:TX拉低,并保持一个bit周期,在这个TX拉低开始后,会有16个时钟来采样后续的1bit周期内的TX电平,来确定这个启动是真的启动而不是电平不稳导致。

               发送:启动之后的8/9bit时间用于数据的发送,流程也是1bit时间有16个时钟采样才确定最终发送数据。

                1bit时间内的16个时钟采样吗,分别在第3、5、7、8、9、10这6个时间内采样,由8、9、10决定最终采样结果:3个相同采样电平则是采样结果,其余按2:1多数发送。

                在启动模式时,如果3个采样不是全0,而是2个0与1个1,会产生一个噪音标志位NE(NOISE ERROR)

数据发送:在1bit时间的中间时间段拉高SCL,表示发送数据。(在中间更能保证数据是稳定而非翻转不及时导致)

STM32F103C8T6所有的USART资源:

                                                        APB2:USART1;

                                                        APB1:USART2,USART3;

对应引脚( 不使用—>不考虑其他应引脚)

                                                        USART1:RX(PA10),TX(PA9);

                                                        USART2:RX(PA3),TX(PA2);

                                                        USART3:RX(PB11),TX(PB10);

10.配置流程:

        开启外设时钟——>利用结构体初始化

                ①开启USART1的外设时钟

                ②定义结构体,初始化结构体参数(波特率、收发模式、停止位时间、奇偶校验、数据字长、数据流控制(没用到?待研究))

                ③用结构体初始化USART1

代码(USART1,只发不收)

usart.c

#include "usart.h"

/* 初始化 USART1:PA9 TX, PA10 RX */
void USART1_Init(uint32_t  baud)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* 使能时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    /* PA9 TX AF 推挽 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* PA10 RX 输入浮空 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* USART 参数 */
    USART_InitStructure.USART_BaudRate = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStructure);

    /* 使能 USART */
    USART_Cmd(USART1, ENABLE);
}

/* 阻塞发送一个字节(等 TC) */
void USART1_SendByte(uint8_t ch)
{
    USART_SendData(USART1, ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

// 发送字符串
void USART1_SendString(char *str)
{
    while (*str)
    {
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, *str++);
    }
}

// 发送数据缓冲区
void USART1_SendDataBuffer(uint8_t *buffer, uint16_t length)
{
    uint16_t i;
    for (i = 0; i < length; i++)
    {
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, buffer[i]);
    }
}

usart.h

#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"
#include <stdio.h>
#include <stdint.h>

void USART1_Init(uint32_t baud);
void USART1_SendByte(uint8_t ch);
void USART1_SendString(char *str);
void USART1_SendDataBuffer(uint8_t *buffer, uint16_t length);

#endif

重定向printf(放在usart.c中即可)

/* 重定向 printf 到 USART1 */
int fputc(int ch, FILE *f)
{
    USART1_SendByte((uint8_t)ch);
    return ch;
}

 main.c

#include "stm32f10x.h"
#include "usart.h"

int main(void)
{
    USART1_Init(115200);
    
    while(1)
    {
            printf("你好\r\n");     
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值