该文档介绍stm32 uart1通过DMA方式发送和接收数据,代码示例基于ucos-ii操作系统。
该文档参考https://wenku.baidu.com/view/d44ef1380975f46526d3e1b5.html 中内容,如有侵权,请告知删除!
有待思考的
!!! 此处的接收缓冲区时来自哪里? uart1的数据缓冲区,还是DMA的接收数据缓冲区,最大支持多少个字节???
!!! DMA发送数据,网上也有看到将配置封装在发送函数中,如
uart1_dma_send_data(uint8_t* buf, uint32_t len),这个好处是,可以变化mem地址(buf数组,以及长度可以适当配置变化),不错!
!!! DMA接收函数,应用DMA中断判断接收完成只能依赖于DMA配置中字节长度,支持DMA传输完成,传输过半,传输错误,但对于不固定长度接收数据,this is a question.
注意:
#include "includes.h"
#define DMA_USART1_DR_Base 0x40013804
void hal_debug_gpio_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void hal_debug_func_config(void)
{
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
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_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_InitStructure);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
USART_Cmd(USART1,ENABLE);
}
void hal_debug_nvic_config(void){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void hal_debug_init(void)
{
hal_debug_gpio_config();
hal_debug_func_config();
hal_debug_nvic_config();
}
void uart_dma_init(void){
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_Cmd(DMA1_Channel4,DISABLE);
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = DMA_USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_Tx_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = USART1_TX_BSIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4,&DMA_InitStructure);
DMA_ClearFlag(DMA1_FLAG_GL4);
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
DMA_Cmd(DMA1_Channel5, DISABLE);
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_Rx_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = USART1_RX_BSIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_ClearFlag(DMA1_FLAG_GL5);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_FLAG_TC4)==SET)
{
DMA_ClearFlag(DMA1_FLAG_GL4);
DMA_Cmd(DMA1_Channel4, DISABLE);
OSMboxPost(mbLumModule_Tx, (void*)1);
}
}
void uart_dma_send_enable(uint16_t size)
{
DMA1_Channel4->CNDTR = (uint16_t)size;
DMA_Cmd(DMA1_Channel4, ENABLE);
}
void uart1_dma_send_data(void)
{
uint8_t err;
uint16_t i;
uint16_t USART1_Tx_Index=0;
for(i=0;i<8;i++){
USART1_Tx_Buf[USART1_Tx_Index++]=i;
}
uart_dma_send_enable(USART1_Tx_Index);
OSMboxPend(mbLumModule_Tx, 5000, &err);
}
void uart1_dma_recv_data(void)
{
uint16_t index = 0;
DMA_Cmd(DMA1_Channel5, DISABLE);
DMA_ClearFlag(DMA1_FLAG_GL5);
DMA1_Channel5->CNDTR = USART1_RX_BSIZE;
DMA_Cmd(DMA1_Channel5, ENABLE);
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
{
uart1_dma_recv_data();
USART_ClearITPendingBit(USART1,USART_IT_IDLE);
}
}
2. app_test.c
该文件为app_test线程,用于1s发送一次串口数据,其中发送串口数据中应用了信号量,如果没有等待到信号量,最大等待时间为5s(加上此处的1s周期则为6s)。
#include "includes.h"
OS_STK gTest[APP_TEST_STK_SIZE];
uint8_t USART1_Tx_Buf[USART1_TX_BSIZE] = {0};
OS_EVENT *gSemEvent1 = NULL;
OS_EVENT *mbLumModule_Tx = NULL;
void app_test(void* p_arg){
(void)p_arg;
gSemEvent1 = OSSemCreate(2);
mbLumModule_Tx = OSMboxCreate((void*)0);
while(1){
OSTimeDly(1000);
uart1_dma_send_data();
}
}
- ucos_main.c
该函数用于创建ucos任务,一个main函数,一个创建任务的任务函数。
其中app_test任务就是这边uart DMA发送数据的任务。
/*
1. 主函数
用于启动ucos-ii操作系统,启动第一个启动任务
2. 启动任务启动其他的任务
*/
static OS_STK gTaskStartStk[APP_TASK_START_STK_SIZE]; //定义栈
static void App_TaskStart(void *p_arg);
static void app_task_create (void);
//1. main
int main(void){
INT8U os_err;
OSInit();
os_err = OSTaskCreateExt((void (*)(void *)) App_TaskStart, /* Create the start task. */
(void * ) 0,
(OS_STK * )&gTaskStartStk[APP_TASK_START_STK_SIZE - 1],
(INT8U ) APP_TASK_START_PRIO,
(INT16U ) APP_TASK_START_PRIO,
(OS_STK * )&gTaskStartStk[0],
(INT32U ) APP_TASK_START_STK_SIZE,
(void * )0,
(INT16U )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));
OSTaskNameSet(APP_TASK_START_PRIO, (INT8U *)"Start Task", &os_err);
OSStart();
}
//2. start task
static void App_TaskStart(void *p_arg)
{
(void)p_arg;
/*hal init*/
hal_dirvers_init();
//printf("uCos-II V2.86 FM.\r\n");
OSStatInit(); /* Determine CPU capacity.*/
//printf("Create App Task.\r\n");
/*creat other app*/
app_task_create();
while(1){
OSTimeDly(1000);
hal_led_toggle(1); //led_toggle
}
}
/*
Create APP Task
*/
static void app_task_create (void){
INT8U os_err;
//test task
os_err = OSTaskCreate(app_test,
(void *)0,
&gTest[APP_TEST_STK_SIZE-1],
APP_TEST_PRIO);
#if (OS_TASK_NAME_SIZE >= 20)
OSTaskNameSet(APP_TEST_PRIO, (INT8U *)"test task", &os_err);
#endif
//led toggle task
/*****************************************************************************************/
os_err = OSTaskCreate((void (*)(void *))app_led_toggle,
(void*)0,
(OS_STK*)&gTaskLedToggle[APP_TASK_LED_STK_SIZE-1],
(INT8U)APP_TASK_LED_PRIO
);
#if (OS_TASK_NAME_SIZE >= 20)
OSTaskNameSet(APP_TASK_LED_PRIO, (INT8U *)"led_toggle", &os_err);
#endif
/*****************************************************************************************/
//task 1
/*****************************************************************************************/
os_err = OSTaskCreate(app_task1,
(void*)0,
&gTask1[APP_TASK1_STK_SIZE-1],
APP_TASK1_PRIO);
/*****************************************************************************************/
//task 2
/*****************************************************************************************/
os_err = OSTaskCreate(app_task2,
(void*)0,
&gTask2[APP_TASK2_STK_SIZE-1],
APP_TASK2_PRIO);
/*****************************************************************************************/
//task 3
/*****************************************************************************************/
os_err = OSTaskCreate(app_task3,
(void*)0,
&gTask3[APP_TASK3_STK_SIZE-1],
APP_TASK3_PRIO);
/*****************************************************************************************/
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)