打印
[APM32F4]

【极海APM32F4xx Tiny】学习笔记02-串口使用教程

[复制链接]
154|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chejia12|  楼主 | 2023-7-21 09:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 chejia12 于 2023-7-23 17:39 编辑

2.串口使用教程
芯片内置多达 6 个通用同步/异步收发器,USART1/6 接口通信速率可达 10.5Mbit/s,其它 USART/UART 的通信速率可达 5.25Mbit/s,

中断源:
  • 发送寄存器为空
  • 发送完成
  • CTS 改变
  • 接收寄存器不为空
  • 过载错误
  • 总线空闲
  • 奇偶校验错误
  • LIN 断开检测
  • 噪音错误
  • 溢出错误
  • 帧错误


串口基本发送初始化流程:
  • 使能gpio时钟和串口外设时钟
  • 设置串口的gpio工作在复用模式
  • 设置gpio的复用功能
  • 配置串口的波特率,关闭流控制,检验位,停止位,数据位
  • 使能串口
  • 编写发送多个字符数据发送函数
  • 重定向printf函数


bsp_uart.h
#ifndef _BSP_USART_H
#define _BSP_USART_H

/* Includes */
#include "main.h"
#include "apm32f4xx.h"
#include "apm32f4xx_gpio.h"
#include "apm32f4xx_rcm.h"
#include "apm32f4xx_usart.h"

typedef enum
{
    COM1 = 0,
    COM2 = 1,
        COMn//串口数量
} COM_TypeDef;




/**
*  USART1
*/
//串口相关
#define TINY_COM1                        USART1
#define TINY_COM1_CLK                    RCM_APB2_PERIPH_USART1
#define TINY_COM1_IRQn                   USART1_IRQn
//发送引脚
#define TINY_COM1_TX_PIN                 GPIO_PIN_9
#define TINY_COM1_TX_GPIO_PORT           GPIOA
#define TINY_COM1_TX_GPIO_CLK            RCM_AHB1_PERIPH_GPIOA
#define TINY_COM1_TX_PIN_SOURCE          GPIO_PIN_SOURCE_9
//接收引脚
#define TINY_COM1_RX_PIN                 GPIO_PIN_10
#define TINY_COM1_RX_GPIO_PORT           GPIOA
#define TINY_COM1_RX_GPIO_CLK            RCM_AHB1_PERIPH_GPIOA
#define TINY_COM1_RX_PIN_SOURCE          GPIO_PIN_SOURCE_10
//引脚复用功能
#define TINY_COM1_GPIO_AF                GPIO_AF_USART1

/**
*USART2
*/
//串口相关
#define TINY_COM2                        USART2
#define TINY_COM2_CLK                    RCM_APB1_PERIPH_USART2
#define TINY_COM2_IRQn                   USART2_IRQn
//发送引脚
#define TINY_COM2_TX_PIN                 GPIO_PIN_2
#define TINY_COM2_TX_GPIO_PORT           GPIOA
#define TINY_COM2_TX_PIN_SOURCE          GPIO_PIN_SOURCE_2
#define TINY_COM2_TX_GPIO_CLK            RCM_AHB1_PERIPH_GPIOA
//接收引脚
#define TINY_COM2_RX_PIN                 GPIO_PIN_3
#define TINY_COM2_RX_GPIO_PORT           GPIOA
#define TINY_COM2_RX_GPIO_CLK            RCM_AHB1_PERIPH_GPIOA
#define TINY_COM2_RX_PIN_SOURCE          GPIO_PIN_SOURCE_3
//引脚复用功能
#define TINY_COM2_GPIO_AF                GPIO_AF_USART2

//调试串口指定
#define DEBUG_USART USART1



/** 函数声明*/
void bsp_uart1_init(uint32_t baud);
void bsp_uart2_init(uint32_t baud);
/*串口写数据*/
void bsp_uart_write(USART_T* usart,uint8_t *dat, uint32_t count);
#endif
bsp_uart.c
/* Includes */
#include "bsp_usart.h"
#include <stdio.h>

/*串口句柄*/
USART_T* COM_USART[COMn] = {TINY_COM1, TINY_COM2};
//串口发送引脚涉及的gpio分组
GPIO_T* COM_TX_PORT[COMn] = {TINY_COM1_TX_GPIO_PORT, TINY_COM2_TX_GPIO_PORT};
//串口接收引脚涉及的gpio分组
GPIO_T* COM_RX_PORT[COMn] = {TINY_COM1_RX_GPIO_PORT, TINY_COM2_RX_GPIO_PORT};
//串口发送引脚涉及的gpio 引脚 pin 外部中断源
const GPIO_PIN_SOURCE_T COM_TX_PIN_SOURCE[COMn] = {TINY_COM1_TX_PIN_SOURCE, TINY_COM2_TX_PIN_SOURCE};
//串口接收引脚涉及的gpio 引脚 pin 外部中断源
const GPIO_PIN_SOURCE_T COM_RX_PIN_SOURCE[COMn] = {TINY_COM1_RX_PIN_SOURCE, TINY_COM2_RX_PIN_SOURCE};
//引脚涉及的复用功能
const GPIO_AF_T COM_GPIO_AF[COMn] = {TINY_COM1_GPIO_AF, TINY_COM2_GPIO_AF};
//串口涉及的外设时钟
const uint32_t COM_USART_CLK[COMn] = {TINY_COM1_CLK, TINY_COM2_CLK};
//发送引脚的使能时钟
const uint32_t COM_TX_PORT_CLK[COMn] = {TINY_COM1_TX_GPIO_CLK, TINY_COM2_TX_GPIO_CLK};
//接收引脚的使能时钟
const uint32_t COM_RX_PORT_CLK[COMn] = {TINY_COM1_RX_GPIO_CLK, TINY_COM2_RX_GPIO_CLK};
//发送引脚
const uint16_t COM_TX_PIN[COMn] = {TINY_COM1_TX_PIN, TINY_COM2_TX_PIN};
//接收引脚
const uint16_t COM_RX_PIN[COMn] = {TINY_COM1_RX_PIN, TINY_COM2_RX_PIN};


/*
    串口重定向
*/

int fputc(int ch, FILE* f)
{
    /* send a byte of data to the serial port */
    USART_TxData(DEBUG_USART, (uint8_t)ch);

    /* wait for the data to be send */
    while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);

    return (ch);
}


/*
串口初始化函数
COM :串口号
configStruct:串口配置结构体
*/
void bsp_uart_init(COM_TypeDef COM, USART_Config_T* configStruct)
{
    GPIO_Config_T GPIO_configStruct;
    GPIO_ConfigStructInit(&GPIO_configStruct);

    /** 使能时钟*/
    RCM_EnableAHB1PeriphClock(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM]);

    if (COM == COM1)
    {
        RCM_EnableAPB2PeriphClock(COM_USART_CLK[COM]);
    }
    else
    {
        RCM_EnableAPB1PeriphClock(COM_USART_CLK[COM]);
    }

    /** 发送引脚复用设置 */
    GPIO_ConfigPinAF(COM_TX_PORT[COM], COM_TX_PIN_SOURCE[COM], COM_GPIO_AF[COM]);

    /** 接收引脚复用设置 */
    GPIO_ConfigPinAF(COM_RX_PORT[COM], COM_RX_PIN_SOURCE[COM], COM_GPIO_AF[COM]);

    /** 配置TX gpio位串口工作模式 */
    GPIO_configStruct.mode = GPIO_MODE_AF;//复用模式
    GPIO_configStruct.pin = COM_TX_PIN[COM];//哪一个pin
    GPIO_configStruct.speed = GPIO_SPEED_50MHz;//速度
    GPIO_Config(COM_TX_PORT[COM], &GPIO_configStruct);

    /**配置串口接收引脚为输入浮空模式 */
    GPIO_configStruct.mode = GPIO_MODE_AF;
    GPIO_configStruct.pin = COM_RX_PIN[COM];
    GPIO_Config(COM_RX_PORT[COM], &GPIO_configStruct);

    /** 配置串口 */
    USART_Config(COM_USART[COM], configStruct);

    /** 使能串口 */
    USART_Enable(COM_USART[COM]);
}

/*!
串口1配置,主要是初始化串口外设的参数
*/
void bsp_uart1_init(uint32_t baud)
{
    USART_Config_T usartConfigStruct;

    /** USART1 configuration */
    usartConfigStruct.baudRate = baud;//波特率
    usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;//关闭流控制
    usartConfigStruct.mode = USART_MODE_TX_RX;//发送接收模式
    usartConfigStruct.parity = USART_PARITY_NONE;//检验
    usartConfigStruct.stopBits = USART_STOP_BIT_1;//停止位
    usartConfigStruct.wordLength = USART_WORD_LEN_8B;//数据位
    bsp_uart_init(COM1, &usartConfigStruct);
}

/*!
串口1配置
*/
void bsp_uart2_init(uint32_t baud)
{
    USART_Config_T usartConfigStruct;

    /** USART1 configuration */
    usartConfigStruct.baudRate = baud;
    usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
    usartConfigStruct.mode = USART_MODE_TX_RX;
    usartConfigStruct.parity = USART_PARITY_NONE;
    usartConfigStruct.stopBits = USART_STOP_BIT_1;
    usartConfigStruct.wordLength = USART_WORD_LEN_8B;
    bsp_uart_init(COM2, &usartConfigStruct);
}
/*!
串口发送函数
dat:待发送的数据
count;发送数据的数量
*
*/
void bsp_uart_write(USART_T* usart,uint8_t *dat, uint32_t count)
{
    while(count--)
    {
        while(USART_ReadStatusFlag(usart, USART_FLAG_TXBE) == RESET);
        USART_TxData(usart, *dat++);
    }
}
使用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

30

帖子

1

粉丝