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