本帖最后由 pq113_6 于 2019-10-29 09:37 编辑
最大支持6组UART。以UART1为例:
1. 配置相应的UART的IO配置
在库文件ac78xx_gpio.h中增加枚举
typedef enum
{
GPIO_INPUT = 0,
GPIO_OUTPUT = 1
}GPIO_Dir_TypeDef;
typedef enum
{
GPIO_FUNC_0 = 0,
GPIO_FUNC_1 = 1,
GPIO_FUNC_2 = 2,
GPIO_FUNC_3 = 3
}GPIO_Func_TypeDef;
GPIOB5/GPIOB6是UART1的TX/RX使用的IO
#define UART1_RX_PIN (GPIO_PB6)
#define UART1_TX_PIN (GPIO_PB5)
设置这2个PIN为UART1模式
GPIO_SetFunc(UART1_RX_PIN, GPIO_FUNC_1);
GPIO_SetFunc(UART1_TX_PIN, GPIO_FUNC_1);
2. 初始化串口
调用库函数int32_t UART_Init(UART_Type *UARTx, UART_SettingType *uartSetting)即可完成UART初始化。
参数的结构定义:
typedef struct {
uint32_t baudrate;
uint8_t dataBits;
uint8_t stopBits;
uint8_t parity;
uint8_t fifoByte;
uint8_t dmaEn; ///< 0; FIFO mode, 1: RX DMA, 2: TX DMA, 3: RX & TX DMA
uint8_t rateStep; ///< sample counter
}UART_SettingType;
参数baudrate/dataBits/stopBits/parity比较好理解,参数parity设置0表示无校验,设置1表示ODD奇校验,设置为2表示EVEN偶校验;fifoByte一般设置1,表示FIFO使能,读写各有2个字节的FIFO(UART的结构框图中有描述,没看到文档说明);damEn表示使用哪种DMA,为0表示不使用DMA功能;参数rateStep对应寄存器SMP_CNT,是BUS时钟分频系数4/8/16,默认16。串口波特率可以通过UARTn_DIV_FRAC [4:0],取值范围是 0 至 31,如下图公式,DIV = {UARTn_DIV_H, UARTn_DIV_L} ; UARTn_DIV_H, UARTn_DIV_L表示整数部分,而UARTn_DIV_FRAC表示小数部分,不过这个参数一般可以设置为0(波特率较小时)
下图是一个例子:
得到的小数部分是0.5634,rateStep = 0.5634*32 = 18。
那程序中是在system_ac78xx.h中配置总线频率的,以默认的8M外部晶振为例:
#define PLL_POSDIV PLL_POSDIV_4
#define PLL_FBKDIV 96
#define PLL_PREDIV PLL_PREDIV_1
#define SYSCLK_DIV SYSCLK_DIVIDER_1
#define APBCLK_DIV APBCLK_DIVIDER_2
#define SYSCLK_FREQ 96000000
#define APB_BUS_FREQ 48000000
APB_BUS_FREQ就是总线频率48MHz。
3. 初始化串口中断
库函数定义中断采用回调函数UART_SetEventCallback(UARTx, UART_IRQHandler),回调函数UART_IRQHandler由客户根据项目情况编写。其函数原型为:
int32_t UART_IRQHandler(uint8_t port, uint32_t LSR0, uint32_t LSR1)
参数port的有效值为1-6,分别表示串口1到串口6。参数LSR0和LSR1是UART的状态寄存器值。一般只使用到LSR0的bit0(DR),表示有数据。
不确定是否需要处理OE(溢出错误标志)。
而使用UART中断一般只使用接收中断,库文件定义了使能接收中断。
UART_SetRxIntEn(UARTx, ENABLE);
最后是是能中断
NVIC_ClearPendingIRQ(UARTx_IRQn);
NVIC_EnableIRQ(UARTx_IRQn);
4. 发送数据
先判断上一笔数据是否已经发送完成,然后调用UART_SendData发送一个字节。
while(!UARTx->UARTn_LSR0.TC);
UART_SendData(UARTx, dat);
5. 接收数据
接收数据的API函数是UART_ReceiveData,接收前也是要判断是否有数据。
if ((UARTx->UARTn_IER.ERXNE == 1) && (LSR0 & LSR0_DR))
{
dat = (uint8_t)(UART_ReceiveData(UARTx) & 0xff);
}
|