发布时间:2022-08-19 12:29
#ifndef _UART_H_
#define _UART_H_
#include "stdint.h"
#include "gd32f30x.h"
#define CACHE_NUM 128
//数据接收处理函数
typedef void (*recv_hanled)(uint8_t *data, uint16_t len);
typedef struct
{
uint32_t usart_periph; //外设名称
uint32_t dma_periph; //dma 外设
dma_channel_enum dma_channelx;//dma外设通道
uint8_t dma_nvic_irq; //dma中断号
uint8_t uart_nvic_irq; //串口中断号
uint8_t dma_or_idle; //传输完成标记和收到一帧数据标记dm
uint16_t data_num; //已经接收到的数据量
uint8_t uart_rx_buffers[CACHE_NUM];//接收数据缓冲区
recv_hanled hanled_fun; //数据接收处理函数
} uart_dam_t;
//初始化串口涉及的时钟和gpio gpio USART/UART
void bsp_uart_gpio_rcu_init(uint32_t usart_periph);
/*基本初始化函数*/
void bsp_uart_usart_base_init(uint32_t usart_periph);
//串口相关自定义结构初始化
uart_dam_t * init_uart_dma_struct(uint32_t usart_periph);
//使能串口中断
void bsp_uart_enable_uart_interrupt(uart_dam_t *puart_dma);
//dma 外设初始化
int bsp_uart_dma_nvic_init(uart_dam_t *puart_dma);
//注册一个处理函数
int bsp_uart_register_handle(uart_dam_t *puart_dma, recv_hanled hanled_fun);
循环调用函数,处理串口信息
void bsp_uart_dma_procees(uint32_t tick);
#endif
#include "uart.h"
#include "stdio.h"
#include "gd32f30x.h"
//每个串口外设一个自定义结构
uart_dam_t uart0_dma;
uart_dam_t uart1_dma;
uart_dam_t uart2_dma;
uart_dam_t uart3_dma;
//接收到的数据个数
volatile uint16_t uart_rxcount[5];
//串口空闲或缓冲器慢标志
volatile uint8_t idle_or_full = 0;
/* 重定向printf函数 */
int fputc(int ch, FILE *f)
{
int cnt = 1000;
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE) && cnt--);
usart_data_transmit(USART1, (uint8_t)ch);
cnt = 1000;
while(RESET == usart_flag_get(USART1, USART_FLAG_TBE) && cnt--);
return ch;
}
//初始化自定义结构体
uart_dam_t * init_uart_dma_struct(uint32_t usart_periph)
{
//UART0 DMA0-CH4
//UART1 DMA0-CH5
//UART2-DMA0-CH2
//UART3-DMA1-CH2
uart_dam_t *puart_dma = NULL;
if(usart_periph == USART0)
{
puart_dma = &uart0_dma;
puart_dma->dma_periph = DMA0;
puart_dma->dma_channelx = DMA_CH4;
puart_dma->dma_nvic_irq = DMA0_Channel4_IRQn;
puart_dma->uart_nvic_irq = USART0_IRQn;
}
else if(usart_periph == USART1)
{
puart_dma = &uart1_dma;
puart_dma->dma_periph = DMA0;
puart_dma->dma_channelx = DMA_CH5;
puart_dma->dma_nvic_irq = DMA0_Channel5_IRQn;
puart_dma->uart_nvic_irq = USART1_IRQn;
}
else if(usart_periph == USART2)
{
puart_dma = &uart2_dma;
puart_dma->dma_periph = DMA0;
puart_dma->dma_channelx = DMA_CH2;
puart_dma->dma_nvic_irq = DMA0_Channel2_IRQn;
puart_dma->uart_nvic_irq = USART2_IRQn;
}
else if(usart_periph == UART3)
{
puart_dma = &uart3_dma;
puart_dma->dma_periph = DMA1;
puart_dma->dma_channelx = DMA_CH2;
puart_dma->dma_nvic_irq = DMA0_Channel2_IRQn;
puart_dma->uart_nvic_irq = UART3_IRQn;
}
puart_dma->usart_periph = usart_periph;
return puart_dma;
}
/*!
\brief 初始化串口涉及的时钟和gpio gpio USART/UART
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
\param[out] none
\retval none
*/
void bsp_uart_gpio_rcu_init(uint32_t usart_periph)
{
/*********************串口0********************/
if(usart_periph == USART0)
{
/* 使能串口时钟 */
rcu_periph_clock_enable(RCU_USART0);
/* 使能gpio时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* gpio IO 初始化发送引脚 */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* 初始化接收引脚 */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
}
/*********************串口0********************/
/*********************串口1********************/
else if(usart_periph == USART1)
{
/* 使能串口时钟 */
rcu_periph_clock_enable(RCU_USART1);
/* 使能gpio时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* gpio IO 初始化发送引脚 */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* 初始化接收引脚 */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
}
/*********************串口1********************/
/*********************串口2********************/
else if(usart_periph == USART2)
{
/* 使能串口时钟 */
rcu_periph_clock_enable(RCU_USART2);
/* 使能gpio时钟 */
rcu_periph_clock_enable(RCU_GPIOB);
/* gpio IO 初始化发送引脚 */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* 初始化接收引脚 */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}
/*********************串口2********************/
/*********************串口3********************/
else if(usart_periph == UART3)
{
/* 使能串口时钟 */
rcu_periph_clock_enable(RCU_UART3);
/* 使能gpio时钟 */
rcu_periph_clock_enable(RCU_GPIOC);
/* gpio IO 初始化发送引脚 */
gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* 初始化接收引脚 */
gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}
/*********************串口3********************/
/*********************串口4********************/
else if(usart_periph == UART4)
{
/* 使能串口时钟 */
rcu_periph_clock_enable(RCU_UART4);
}
/*********************串口4********************/
}
/*基本初始化函数*/
void bsp_uart_usart_base_init(uint32_t usart_periph)
{
//外设的gpio初始化和时钟初始化
bsp_uart_gpio_rcu_init(usart_periph);
/* USART configure 串口参数初始化 */
usart_deinit(usart_periph);
//设置波特率
usart_baudrate_set(usart_periph, 115200U);
//设置数据长度
usart_word_length_set(usart_periph, USART_WL_8BIT);
//设置停止位
usart_stop_bit_set(usart_periph, USART_STB_1BIT);
//设置检验位
usart_parity_config(usart_periph, USART_PM_NONE);
//硬件流管理 都关闭
usart_hardware_flow_rts_config(usart_periph, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(usart_periph, USART_CTS_DISABLE);
//串口接收使能
usart_receive_config(usart_periph, USART_RECEIVE_ENABLE);
//串口发送使能
usart_transmit_config(usart_periph, USART_TRANSMIT_ENABLE);
//使能串口
usart_enable(usart_periph);
}
/*
使能串口中断
*/
void bsp_uart_enable_uart_interrupt(uart_dam_t *puart_dma)
{
/*中断管理器使能,并分配优先级*/
nvic_irq_enable(puart_dma->uart_nvic_irq, 1, 1);
/*清除中断标志*/
usart_interrupt_flag_clear(puart_dma->usart_periph, USART_INT_FLAG_IDLE);
/* 使能串口中断 */
usart_interrupt_enable(puart_dma->usart_periph, USART_INT_IDLE);//空闲中断
}
/*
功能:DMA 中断接收数据,uart5 不可以使用dma传输数据
hope_len:希望接收的数据个数
circulation:是否使用连续模式
*/
int bsp_uart_dma_nvic_init(uart_dam_t *puart_dma)
{
dma_parameter_struct dma_init_struct;
if(puart_dma == NULL)
{
return 0;
}
/* enable DMA0 clock 使能DMA0 的时钟*/
if(puart_dma->usart_periph == USART0 ||
puart_dma->usart_periph == USART1 ||
puart_dma->usart_periph == USART2)
{
rcu_periph_clock_enable(RCU_DMA0);
}
else if(puart_dma->usart_periph == UART3)
{
rcu_periph_clock_enable(RCU_DMA1);
}
//中断管理器开启通道中断
nvic_irq_enable(puart_dma->dma_nvic_irq, 0, 1);
// 复位代码指定通道
dma_deinit(puart_dma->dma_periph, puart_dma->dma_channelx);
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; //外设到内存
dma_init_struct.memory_addr = (uint32_t)puart_dma->uart_rx_buffers; //接收缓冲区开始地址
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//内存地址自动增长
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;//数据长度8bit
dma_init_struct.number = CACHE_NUM;//缓冲区大小
#define USART0_DATA_ADDRESS ((uint32_t)&USART_DATA(USART0))
dma_init_struct.periph_addr = USART0_DATA_ADDRESS;//外设寄存器地址
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//外设寄存器地址不自动增加
dma_init_struct.memory_width = DMA_PERIPHERAL_WIDTH_8BIT;//外输数据宽度
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;//DMA优先级
dma_init(puart_dma->dma_periph, puart_dma->dma_channelx, &dma_init_struct);
dma_circulation_enable(puart_dma->dma_periph, puart_dma->dma_channelx);//连续传输
//数据传输方式不是内存到内存
dma_memory_to_memory_disable(puart_dma->dma_periph, puart_dma->dma_channelx);
/* USART DMA0 串口0DMA 数据接收使能 */
usart_dma_receive_config(puart_dma->usart_periph, USART_DENR_ENABLE);
/* enable DMA0 串口0 DMA 接收完成中断使能 */
dma_interrupt_enable(puart_dma->dma_periph, puart_dma->dma_channelx, DMA_INT_FTF);
/* enable DMA0 启用指定的DMA通道*/
dma_channel_enable(puart_dma->dma_periph, puart_dma->dma_channelx);
return 1;
}
/*
禁止中断和DMA
*/
void bsp_uart0_init_idle_it_disable()
{
//禁止中断
nvic_irq_disable(USART0_IRQn);
usart_interrupt_disable(USART0, USART_INT_IDLE);//空闲中断
//禁止DMA
dma_channel_disable(DMA0, DMA_CH4);
}
/*
串口0中断处理函数
*/
void USART0_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart0_dma;
if(RESET != usart_interrupt_flag_get(p_uart_dma->usart_periph, USART_INT_FLAG_IDLE))
{
usart_data_receive(p_uart_dma->usart_periph);
p_uart_dma->data_num = CACHE_NUM - dma_transfer_number_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
p_uart_dma->dma_or_idle = 1;
//重新使能dma,重新计算剩余未传输数量
dma_channel_disable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
DMA_CHCNT(p_uart_dma->dma_periph, p_uart_dma->dma_channelx) = CACHE_NUM;
dma_channel_enable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
}
}
/*
串口3中断处理函数
*/
void USART1_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart1_dma;
if(RESET != usart_interrupt_flag_get(p_uart_dma->usart_periph, USART_INT_FLAG_IDLE))
{
usart_data_receive(p_uart_dma->usart_periph);
p_uart_dma->data_num = CACHE_NUM - dma_transfer_number_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
p_uart_dma->dma_or_idle = 1;
//重新使能dma,重新计算剩余未传输数量
dma_channel_disable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
DMA_CHCNT(p_uart_dma->dma_periph, p_uart_dma->dma_channelx) = CACHE_NUM;
dma_channel_enable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
}
}
/*
串口2中断处理函数
*/
void USART2_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart2_dma;
if(RESET != usart_interrupt_flag_get(p_uart_dma->usart_periph, USART_INT_FLAG_IDLE))
{
usart_data_receive(p_uart_dma->usart_periph);
p_uart_dma->data_num = CACHE_NUM - dma_transfer_number_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
p_uart_dma->dma_or_idle = 1;
//重新使能dma,重新计算剩余未传输数量
dma_channel_disable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
DMA_CHCNT(p_uart_dma->dma_periph, p_uart_dma->dma_channelx) = CACHE_NUM;
dma_channel_enable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
}
}
/*
串口3中断处理函数
*/
void UART3_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart3_dma;
if(RESET != usart_interrupt_flag_get(p_uart_dma->usart_periph, USART_INT_FLAG_IDLE))
{
usart_data_receive(p_uart_dma->usart_periph);
p_uart_dma->data_num = CACHE_NUM - dma_transfer_number_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
p_uart_dma->dma_or_idle = 1;
//重新使能dma,重新计算剩余未传输数量
dma_channel_disable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
DMA_CHCNT(p_uart_dma->dma_periph, p_uart_dma->dma_channelx) = CACHE_NUM;
dma_channel_enable(p_uart_dma->dma_periph, p_uart_dma->dma_channelx);
}
}
/*串口0dma*/
void DMA0_Channel4_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart0_dma;
//获取中断标记并判断否是置位
if(dma_interrupt_flag_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_FTF))
{
//清除dma中断标记
dma_interrupt_flag_clear(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_G);
p_uart_dma->dma_or_idle = SET;
}
}
/*串口1 dma*/
void DMA0_Channel5_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart1_dma;
//获取中断标记并判断否是置位
if(dma_interrupt_flag_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_FTF))
{
//清除dma中断标记
dma_interrupt_flag_clear(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_G);
p_uart_dma->dma_or_idle = SET;
}
}
/*串口2 dma*/
void DMA0_Channel2_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart2_dma;
//获取中断标记并判断否是置位
if(dma_interrupt_flag_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_FTF))
{
//清除dma中断标记
dma_interrupt_flag_clear(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_G);
p_uart_dma->dma_or_idle = SET;
}
}
/*串口3 dma*/
void DMA1_Channel2_IRQHandler(void)
{
uart_dam_t *p_uart_dma = &uart3_dma;
//获取中断标记并判断否是置位
if(dma_interrupt_flag_get(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_FTF))
{
//清除dma中断标记
dma_interrupt_flag_clear(p_uart_dma->dma_periph, p_uart_dma->dma_channelx, DMA_INT_FLAG_G);
p_uart_dma->dma_or_idle = SET;
}
}
/*注册一个处理函数*/
int bsp_uart_register_handle(uart_dam_t *puart_dma, recv_hanled hanled_fun)
{
puart_dma->hanled_fun = hanled_fun;
}
//循环调用函数用于处理各个串口数据
void bsp_uart_dma_procees(uint32_t tick)
{
if(uart0_dma.dma_or_idle)
{
uart_dam_t *puart_dma = &uart0_dma;
puart_dma->dma_or_idle = 0;
puart_dma->hanled_fun(puart_dma->uart_rx_buffers, puart_dma->data_num);
puart_dma->data_num = 0;
}
else if(uart1_dma.dma_or_idle)
{
uart_dam_t *puart_dma = &uart1_dma;
puart_dma->dma_or_idle = 0;
puart_dma->hanled_fun(puart_dma->uart_rx_buffers, puart_dma->data_num);
puart_dma->data_num = 0;
}
if(uart2_dma.dma_or_idle)
{
uart_dam_t *puart_dma = &uart2_dma;
puart_dma->dma_or_idle = 0;
puart_dma->hanled_fun(puart_dma->uart_rx_buffers, puart_dma->data_num);
puart_dma->data_num = 0;
}
if(uart3_dma.dma_or_idle)
{
uart_dam_t *puart_dma = &uart3_dma;
puart_dma->dma_or_idle = 0;
puart_dma->hanled_fun(puart_dma->uart_rx_buffers, puart_dma->data_num);
puart_dma->data_num = 0;
}
}
#include "gd32f30x.h"
#include "gd32f303_sys.h"
#include "systick.h"
#include "uart.h"
#include "stdio.h"
#include "adc.h"
#include "button.h"
#include "bsp_gpio.h"
#include "at24cxx.h"
void uart0_recv_hanled(uint8_t *data, uint16_t len)
{
printf("read len = %d:", len);
for(int i = 0; i < len; i++)
{
printf("%02x ", (int)data[i]);
}
printf("\r\n");
}
/*!
主函数:
*/
int main(void)
{
/* 配置系统时钟 */
systick_config();
//设置中断分组
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
/* gpio时钟使能*/
// 配置MCU调试下载使用swd方式,同时将pb3 和PB4 作为普通gpio
rcu_periph_clock_enable(RCU_AF);
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
//gpio
bsp_gpio_init();
//串口初始化
bsp_uart_gpio_rcu_init(USART0);
bsp_uart_usart_base_init(USART0);
//下边是串口的数据接收使用dma方式需要调用和函数
uart_dam_t *uart_dma = init_uart_dma_struct(USART0);
bsp_uart_enable_uart_interrupt(uart_dma);
bsp_uart_dma_nvic_init(uart_dma);
bsp_uart_register_handle(uart_dma, uart0_recv_hanled);
// bsp_at24c02_init();
printf("hello gd32\r\n");
//初始化ADC
// adc_init();
// init_btn();
BEEP = 0;
while(1)
{
if(tick % 500 == 0)
{
LED0 = !LED0;
LED1 = !LED1;
LED2 = !LED2;
}
//循环调用
bsp_uart_dma_procees(tick);
}
}
【C++】C++核心编程部分-内存分区模型-引用-函数提高-类与对象-文件操作
macbook linux 双系统,MacOS+Ubuntu双系统,原来MacBook安装linux也简单!
(附源码)springboot电竞专题网站 毕业设计 641314
Fullcalendar日历使用,包括视图选择、事件插入、编辑事件、事件状态更改、事件添加和删除、事件拖动调整,自定义头部,加入el-popover显示图片、图片预览、添加附件链接等,支持手机显示。
STM32的启动过程 — startup_xxxx.s文件解析(MDK和GCC双环境)
苹果出现长方形透明框_看到我卧槽!这是苹果史上最疯狂的开发者大会