STM32——15.串口发送与接收&打印函数重定向

串口通信

  • 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统。

  • 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发。

  • 名称 引脚 双工 时钟 电平 设备
    USART TX、RX 全双工 异步 单端 点对点
    I2C SCL、SDA 半双工 同步 单端 多设备
    SPI SCLK、MOSI、MISO、CS 全双工 同步 单端 多设备
    CAN CAN_H、CAN_L 半双工 异步 差分 多设备
    USB DP、DM 半双工 异步 差分 点对点
  • 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。

  • 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力。

  • 硬件电路

  • 简单双向串口通信有两根通信线(发送端TX和接收端RX)。

  • TX与RX要交叉连接。

  • 当只需单向的数据传输时,可以只接一根通信线。

  • 当电平标准不一致时,需要加电平转换芯片

  • 电平标准

  • 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

  • TTL电平:+3.3V或+5V表示1,0V表示0。

  • RS232电平:-3~-15V表示1,+3~+15V表示0。

  • RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)(理论可达一千多米)

  • 串口参数及时序

  • 波特率:串口通信的速率

  • 起始位:标志一个数据帧的开始,固定为低电平

  • 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行。

  • 校验位:用于数据验证,根据数据位计算得来

  • 停止位:用于数据帧间隔,固定为高电平

  • USART简介

  • USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器。

  • USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。

  • 自带波特率发生器,最高达4.5Mbits/s

  • 可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)

  • 可选校验位(无校验/奇校验/偶校验)

  • 支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN

  • STM32F103C8T6 USART资源: USART1、 USART2、 USART3

  • USART基本结构(初始化通常根据这个来)

  • ---------------------Serial.c------------------------------------------------------------------
    #include "stm32f10x.h"                  // Device header
    #include <stdio.h>
    ​
    /*
    看基本结构图写步骤:
    1.开启时钟,把需要用到的USART和GPIO时钟打开。
    2.GPIO初始化,把TX配置成复用输入,RX设置成输入
    3.USART初始化,使用结构体初始化。
    4.开启发送功能,USART(如果需要接受就使用中断)
    */
    ​
    void Serial_Init(void)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        USART_InitTypeDef USART_InitStruct;
        USART_InitStruct.USART_BaudRate =9600;
        USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStruct.USART_Mode = USART_Mode_Tx;
        USART_InitStruct.USART_Parity = USART_Parity_No;
        USART_InitStruct.USART_StopBits = USART_StopBits_1;
        USART_InitStruct.USART_WordLength = USART_WordLength_8b;
        
        USART_Init(USART1 , &USART_InitStruct);
        
        USART_Cmd(USART1 , ENABLE);
        
    }
    ​
    //发送一个字节
    void Serial_SendByte(uint8_t Byte)
    {
        USART_SendData(USART1 , Byte);
        //判断标志位是否为0,防止数据覆盖
        while (USART_GetFlagStatus(USART1 , USART_FLAG_TXE) == RESET);
        
    }
    ​
    //发送一个数组
    void Serial_SendArray(uint8_t *Array , uint16_t Length)
    {
        uint8_t i;
        for(i = 0 ; i < Length ; i++)
        {
            Serial_SendByte(Array[i]);
        }
    }
    ​
    //发送一个字符串
    void Serial_SendString(char *String)
    {
        uint8_t i;
        for(i = 0 ; String[i] != '\0' ; i++)
        {
            Serial_SendByte(String[i]);
        }
    }
    ​
    //求取次方结果
    uint32_t Get_Pow(uint8_t x , uint8_t y)
    {
        uint32_t Result = 1;
        while(y--)
        {
            Result *= x;
        }
        return Result;
    }
    ​
    //发送一个数字
    void Serial_SendNumber(uint32_t Num , uint8_t Length)
    {
        //将数字,一个一个都提取出来,在单独发送
        //362 / 100 = 3.62  % 10 = 3
        uint8_t i;
        for(i = 0 ; i < Length ; i++)
        {
            Serial_SendByte(Num / Get_Pow(10 , Length - i - 1) % 10 + '0'); //0是为了显示数字
        }
        
    }
    ​
    //重写fputc函数,完成重定向,将打印的数据显示到串口
    //还有升级版,重新看视频
    int fputc(int ch , FILE *f)
    {
        Serial_SendByte(ch);
        return ch;
    }    
    ---------------------Serial.h------------------------------------------------------------------    
    #ifndef __SERIAL_H
    #define __SERIAL_H
    ​
    #include <stdio.h>
    ​
    void Serial_Init(void);
    void Serial_SendByte(uint8_t Byte);
    void Serial_SendArray(uint8_t *Array , uint16_t Length);
    void Serial_SendString(char *String);
    void Serial_SendNumber(uint32_t Num , uint8_t Length);
    ​
    #endif    
    ---------------------main.c------------------------------------------------------------------
    #include "stm32f10x.h"   
    #include "OLED.h"
    #include "Serial.h"
    ​
    int main(void)
    {
        OLED_Init();
        Serial_Init();
    //  Serial_SendByte(0x41);
    //  Serial_SendByte('B');
        
    //  uint8_t arr[] = {0x51,0x52,0x53,0x54};
    //  Serial_Array(arr , 4);
    //  Serial_SendString("Hello world!");
        
    //  Serial_SendNumber(18990925 , 8);
        
        //printf重定向
        //printf("Num = %d\r\n" , 888);
        
        //显示中文,将c/c++那个设置哪里填上--no-multibyte-chars 。还有记得选utf-8
        //串口助手也设置utf-8就可以了。
        printf("星辰物语");
        while(1)
        {
    ​
        }
    }
            

    作者:m0_48261292

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32——15.串口发送与接收&打印函数重定向

    发表回复