熊爸的学习时间

STM32一文通(8) 串口通讯

2020-08-06  本文已影响0人  熊爸天下_56c7

一.原生串口通讯

二. 串口与PC通讯

三. RS232标准串口通讯

四. STM32串口

1. 内部结构

寄存器 功能
TX 数据发送
RX 数据接收
SCLK 时钟,仅同步通信时使用(不常用)
nRTS 发送请求(不常用)
nCTS 允许发送 (不常用)

2. 串口引脚分布

注意:串口一是APB2总线, 其他是APB1总线

3. 串口引脚重定义

参见复用重映射和调试I/O配置寄存器(AFIO_MAPR)

4. 串口寄存器

(1). 串口数据寄存器 USART_DR

USART_DR, 9位有效
USART_DR一个地址对应了两个物理内存。包含一个发送数据寄存器TDR和一个接收数据寄存器RDR。

(2). 串口数据寄存器 USART_CR1 USART_CR2 用来配置串口

(3). 串口波特率寄存器USART_BRR

五. 串口相关结构体

1. 串口初始化结构体 USART_InitTypeDef

typedef struct
{
  uint32_t USART_BaudRate;            /*!< This member configures the USART communication baud rate.
                                           The baud rate is computed using the following formula:
                                            - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
                                            - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */

  uint16_t USART_WordLength;          /*!< Specifies the number of data bits transmitted or received in a frame.
                                           This parameter can be a value of @ref USART_Word_Length */

  uint16_t USART_StopBits;            /*!< Specifies the number of stop bits transmitted.
                                           This parameter can be a value of @ref USART_Stop_Bits */

  uint16_t USART_Parity;              /*!< Specifies the parity mode.
                                           This parameter can be a value of @ref USART_Parity
                                           @note When parity is enabled, the computed parity is inserted
                                                 at the MSB position of the transmitted data (9th bit when
                                                 the word length is set to 9 data bits; 8th bit when the
                                                 word length is set to 8 data bits). */
 
  uint16_t USART_Mode;                /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
                                           This parameter can be a value of @ref USART_Mode */

  uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
                                           or disabled.
                                           This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;

发送接收都使能

USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送接收都使能

2.同步时钟初始化结构体 (用的少)

typedef struct
{

  uint16_t USART_Clock;   /*!< Specifies whether the USART clock is enabled or disabled.
                               This parameter can be a value of @ref USART_Clock */

  uint16_t USART_CPOL;    /*!< Specifies the steady state value of the serial clock.
                               This parameter can be a value of @ref USART_Clock_Polarity */

  uint16_t USART_CPHA;    /*!< Specifies the clock transition on which the bit capture is made.
                               This parameter can be a value of @ref USART_Clock_Phase */

  uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted
                               data bit (MSB) has to be output on the SCLK pin in synchronous mode.
                               This parameter can be a value of @ref USART_Last_Bit */
} USART_ClockInitTypeDef;

六. 串口相关库函数

1. 串口初始化函数 USART_Init()

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)

示例:

USART_InitStructure.USART_BaudRate=115200; //设置波特率
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_Rx | USART_Mode_Tx; //设置收发使能
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);

2. 中断配置函数 USART_ITConfig()

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)

例:使能接受完毕中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

3. 串口使能函数 USART_Cmd

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)

4. 数据发送函数 USART_SendData()

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)

5. 数据接收函数 USART_ReceiveData

uint16_t USART_ReceiveData(USART_TypeDef* USARTx)

6.中断状态位获取函数 USART_GetITStatus

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)

7. 编程方法

例子:

psb_usart.h文件(这个文件将5个串口都定义好了, 通过选择编译来确定串口)

#ifndef __BSP_USART_H
#define __BSP_USART_H

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

//用哪个串口就把哪个置1
#define DEBUG_USART1     1
#define DEBUG_USART2     0
#define DEBUG_USART3     0
#define DEBUG_USART4     0
#define DEBUG_USART5     0

#if DEBUG_USART1
// 串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

#elif DEBUG_USART2
//串口2-USART2
#define  DEBUG_USARTx                   USART2
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART2
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_2
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_3

#define  DEBUG_USART_IRQ                USART2_IRQn
#define  DEBUG_USART_IRQHandler         USART2_IRQHandler

#elif DEBUG_USART3
//串口3-USART3
#define  DEBUG_USARTx                   USART3
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART3
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOB)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOB   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOB
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                USART3_IRQn
#define  DEBUG_USART_IRQHandler         USART3_IRQHandler

#elif DEBUG_USART4
//串口4-UART4
#define  DEBUG_USARTx                   UART4
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART4
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOC
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                UART4_IRQn
#define  DEBUG_USART_IRQHandler         UART4_IRQHandler

#elif DEBUG_USART5
//串口5-UART5
#define  DEBUG_USARTx                   UART5
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART5
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_12
#define  DEBUG_USART_RX_GPIO_PORT       GPIOD
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_2

#define  DEBUG_USART_IRQ                UART5_IRQn
#define  DEBUG_USART_IRQHandler         UART5_IRQHandler

#endif

void USART_Config(void);
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data);
void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data);
void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array,uint8_t num);
void Usart_SendStr(USART_TypeDef* pUSARTx, char *str);
#endif  /* __BSP_USART_H */

psb_usart.c

#include "psb_usart.h"
static void NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;//中断初始化结构体
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//先设组
    NVIC_InitStruct.NVIC_IRQChannel = DEBUG_USART_IRQ;//中断源
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//主优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority=7;//从优先级
    NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE; //中断使能
    
    NVIC_Init(&NVIC_InitStruct); //中断初始化
}
void USART_Config(void)
{
    //0.变量定义区
    GPIO_InitTypeDef GPIO_InitStructure; //创建一个GPIO_InitTypeDef类型的数据
    USART_InitTypeDef USART_InitStruct;//串口初始化结构体
    
    //1.配置GPIO
    DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); //开启时钟
    
    // 将USART Tx的GPIO配置为推挽复用模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
    GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
    
    //2.初始化串口
    DEBUG_USART_APBxClkCmd(RCC_APB2Periph_USART1,ENABLE);
    
    USART_InitStruct.USART_BaudRate = DEBUG_USART_BAUDRATE; //波特率
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;//8位数据为
    USART_InitStruct.USART_StopBits = USART_StopBits_1; //停止位1
    USART_InitStruct.USART_Parity = USART_Parity_No;  //无奇偶校验
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送接收都使能
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流 
    
    USART_Init(USART1, &USART_InitStruct);//初始化串口
    
    //3.中断配置
    NVIC_Config();
    // 使能串口接收中断
    USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);    
    
    //4. 使能串口
    USART_Cmd(DEBUG_USARTx, ENABLE);
    
}
/*----------------------------------------------------------------------*/
//5. 编写发送函数

//发送一个字节
void Usart_SendByte(USART_TypeDef* USARTx,uint8_t data)
{
    USART_SendData(USARTx, data);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)==RESET);
}
//发送两个字节
void Usart_SendHalfWord(USART_TypeDef* USARTx,uint16_t data)
{
    uint8_t tempH, tempL;
    tempL =  data & 0xFF;
    tempH =  (data>>8) & 0xFF;
    Usart_SendByte(USARTx,tempH);
    Usart_SendByte(USARTx,tempL);
}
//发送一个数组
void Usart_SendArray(USART_TypeDef* USARTx,uint8_t *array, uint8_t num)
{
    uint8_t i;
    for(i=0;i<num;i++)
    {
        Usart_SendByte(USARTx,*array++);
    }
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
}
//发送一个字符串
void Usart_SendStr(USART_TypeDef* pUSARTx, char *str)
{
    uint8_t i=0;
    do
  {
        Usart_SendByte(pUSARTx, *(str+i));
        i++;
    }while(*(str+i) != '\0');
    while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET );
}

//重定向c库函数printf到串口,重定向后可使用printf函数和putchar函数
int fputc(int ch, FILE *f)
{
        /* 发送一个字节数据到串口 */
        USART_SendData(DEBUG_USARTx, (uint8_t) ch);
        
        /* 等待发送完毕 */
        while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);     
    
        return (ch);
}

/*----------------------------------------------------------------------*/
//6. 编写接收函数
uint16_t Rev_Byte(void)
{
    return USART_ReceiveData(DEBUG_USARTx);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
        /* 等待串口输入数据 */
        while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

        return (int)USART_ReceiveData(DEBUG_USARTx);
}
/*----------------------------------------------------------------------*/

中断部分

#include "stm32f10x_it.h"
#include "psb_usart.h"
#include "led.h"

//省略未修改内容

void DEBUG_USART_IRQHandler(void)
{
  uint8_t ucTemp;
    if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
    {       
        ucTemp = getchar();
    USART_SendData(DEBUG_USARTx,ucTemp); 
            switch(ucTemp)
            {
                case '0':
                    LED_R(ON);
                    LED_G(OFF);
                    LED_B(OFF);
                break;
                case '1':
                    LED_R(OFF);
                    LED_G(ON);
                    LED_B(OFF);
                break;
                case '2':
                    LED_R(OFF);
                    LED_G(OFF);
                    LED_B(ON);
                break;
                default:
                    LED_R(OFF);
                    LED_G(OFF);
                    LED_B(OFF);
                    break;
            }
    }
}

main.c随便写

#include "stm32f10x.h"
#include "led.h"
#include "psb_usart.h"

int main(void)
{
    uint8_t a[11]= {0,1,2,3,4,5,6,7,8,9,10};
    LED_GPIO_Config();
    USART_Config();
    LED_B(OFF);
    LED_R(OFF);
    LED_G(OFF);
    
    //Usart_SendByte(DEBUG_USARTx,0x08);
    //Usart_SendHalfWord(DEBUG_USARTx,0xabcd);
    //Usart_SendArray(DEBUG_USARTx, a,11);
    //Usart_SendStr(DEBUG_USARTx,"滚滚长江东逝水\n");
    //printf("浪花淘尽英雄~\n");
    printf("PC端输入:0,1,2可以点亮RGB~\n");
}
上一篇 下一篇

猜你喜欢

热点阅读