N32串口空闲中断DMA接收不定长数据
N32串口接收与发送
接收部分如下图,USART_DAT寄存器只有8位可用,也就是一次写入一个字节;调用: USART1->DAT
DMA空闲中断接收不定长数据:
在UART1空闲中断服务函数中禁用DMA通道之后再启用DMA通道 DMA才不会从尾部继续写入数据
使用如下
DMA_Channel_Enable/DMA_Channel_Disable
而不是使用
USART_DMA_Transfer_Disable/USART_DMA_Transfer_Enable
配置DMAChannel对应的DMA请求DMA_Channel_Request_Remap
DMA_Channel_Request_Remap( UART1_DMA_Channel, DMA_REMAP_USART1_RX);
空闲中断接收不定长数据代码:
function.c
#include "main.h"
#include "function.h"
#include <stdio.h>
USART_InitType myUart_1;
GPIO_InitType myGPIOA_RXTX;
DMA_InitType my_dma_uart;
uint8_t RX_Buffer[ RX_BUFFERSIZE ];
void my_GPIO_Init( void )
{
// UART1 GPIO TX-PA9-AF4 RX-PA10-AF4
RCC_AHB_Peripheral_Clock_Enable( RCC_AHB_PERIPH_GPIOA );
// LED GPIOB
RCC_AHB_Peripheral_Clock_Enable( RCC_AHB_PERIPH_GPIOB );
GPIO_Structure_Initialize( &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = UART1_RX_Pin;
myGPIOA_RXTX.GPIO_Mode = GPIO_MODE_AF_PP;
myGPIOA_RXTX.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
myGPIOA_RXTX.GPIO_Alternate = GPIO_AF5_USART1;
myGPIOA_RXTX.GPIO_Pull = GPIO_NO_PULL;
GPIO_Peripheral_Initialize( UART1_Port, &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = UART1_TX_Pin;
myGPIOA_RXTX.GPIO_Alternate = GPIO_AF5_USART1;
GPIO_Peripheral_Initialize( UART1_Port, &myGPIOA_RXTX );
// LED
GPIO_Structure_Initialize( &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = LED_1_PIN;
myGPIOA_RXTX.GPIO_Mode = GPIO_MODE_OUT_PP;
myGPIOA_RXTX.GPIO_Pull = GPIO_NO_PULL;
myGPIOA_RXTX.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
GPIO_Peripheral_Initialize( LED_PORT, &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = LED_2_PIN;
GPIO_Peripheral_Initialize( LED_PORT, &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = LED_3_PIN;
GPIO_Peripheral_Initialize( LED_PORT, &myGPIOA_RXTX );
myGPIOA_RXTX.Pin = LED_4_PIN;
GPIO_Peripheral_Initialize( LED_PORT, &myGPIOA_RXTX );
return;
}
void my_UART_Init( void )
{
RCC_APB2_Peripheral_Clock_Enable( RCC_APB2_PERIPH_USART1 );
USART_Structure_Initializes( &myUart_1 );
myUart_1.BaudRate = 115200;
myUart_1.HardwareFlowControl = USART_HFCTRL_NONE;
myUart_1.Mode = USART_MODE_RX | USART_MODE_TX;
myUart_1.Parity = USART_PE_NO;
myUart_1.StopBits = USART_STPB_1;
myUart_1.WordLength = USART_WL_8B;
USART_Initializes( USART1, &myUart_1 );
USART_Enable( USART1 );
return;
}
int fputc(int ch, FILE* f)
{
USART_Data_Send(USART1, (uint8_t)ch);
while (USART_Flag_Status_Get(USART1, USART_FLAG_TXDE) == RESET)
;
return (ch);
}
void my_DMA_Init( void )
{
/* 定义结构体 打开时钟 初始化通道 配置结构体 初始化DMA 映射请求 ->外部再启动DMA USART_DMA_Transfer_Enable() DMA_Channel_Enable() */
RCC_AHB_Peripheral_Clock_Enable( RCC_AHB_PERIPH_DMA ); // 时钟树 DMA挂载在AHB总线上
DMA_Reset( UART1_DMA_Channel ); // N32 8 个可独立配置的 DMA 通道; N32G430手册P188->总共52个DMA请求,可以灵活配置映射; 此行只是初始化通道
/*******************************************************/
my_dma_uart.PeriphAddr = ( uint32_t )&USART1->DAT; // G430用户手册P478 USART的DAT寄存器 数据寄存器是USART基地址+0x04; (官方标准库居然没有宏定义...
my_dma_uart.MemAddr = ( uint32_t )RX_Buffer;
my_dma_uart.Direction = DMA_DIR_PERIPH_SRC; // 方向 外设是数据源; Memory是Dst Destination
my_dma_uart.BufSize = RX_BUFFERSIZE;
my_dma_uart.PeriphInc = DMA_PERIPH_INC_MODE_DISABLE; // 外设不增量
my_dma_uart.MemoryInc = DMA_MEM_INC_MODE_ENABLE; // 内存地址自增
my_dma_uart.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
my_dma_uart.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;
my_dma_uart.CircularMode = DMA_CIRCULAR_MODE_DISABLE;
// my_dma_uart.CircularMode = DMA_CIRCULAR_MODE_ENABLE;
my_dma_uart.Priority = DMA_CH_PRIORITY_HIGHEST;
my_dma_uart.Mem2Mem = DMA_MEM2MEM_DISABLE;
/*******************************************************/
DMA_Initializes( UART1_DMA_Channel, &my_dma_uart );
DMA_Channel_Request_Remap( UART1_DMA_Channel, UART1_DMA_Remap_Config ); // 此处才是映射请求到DMA通道
DMA_Channel_Enable( UART1_DMA_Channel );
return;
}
void my_NVIC_Init( void )
{
NVIC_InitType my_NVIC_InitStruct;
/* IRQn_Type 根据Cortex-M3M4权威指南所述 芯片厂家会自己再设定中断号 所以应该到n32g430.h中找中断而不是到core_cm4.h中 */
my_NVIC_InitStruct.NVIC_IRQChannel = UART1_Interrupt_IRQn;
my_NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
my_NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
my_NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Initializes( &my_NVIC_InitStruct );
return;
}
void USART1_CLS_IDLEFlag( void )
{
uint32_t Reg_Temp;
Reg_Temp = USART1->STS;
Reg_Temp = USART1->DAT;
return;
}
function.h
#ifndef __FUNCTION_H_
#define __FUNCTION_H_
void my_GPIO_Init( void );
void my_UART_Init( void );
void my_DMA_Init( void );
void my_NVIC_Init( void );
void USART1_CLS_IDLEFlag( void );
extern USART_InitType myUart_1;
extern GPIO_InitType myGPIOA_RXTX;
extern DMA_InitType my_dma_uart;
#define UART1_RX_Pin GPIO_PIN_10
#define UART1_TX_Pin GPIO_PIN_9
#define UART1_Port GPIOA
#define LED_PORT GPIOB
#define LED_1_PIN GPIO_PIN_13
#define LED_2_PIN GPIO_PIN_3
#define LED_3_PIN GPIO_PIN_8
#define LED_4_PIN GPIO_PIN_14
#define RX_BUFFERSIZE 60
#define UART1_DMA_Channel DMA_CH1
#define UART1_DMA_Remap_Config DMA_REMAP_USART1_RX
#define UART1_Interrupt_IRQn USART1_IRQn
extern uint8_t RX_Buffer[ RX_BUFFERSIZE ];
#endif
n32g430_it.c
#include "n32g430_it.h"
#include "main.h"
#include "function.h"
#include <stdio.h>
#include <string.h>
/* 启动文件中可找到 */
void USART1_IRQHandler(void)
{
if( RESET != USART_Flag_Status_Get( USART1, USART_FLAG_IDLEF ) )
{
uint8_t count = 0;
// USART_DMA_Transfer_Disable( USART1, USART_DMAREQ_RX );
DMA_Channel_Disable( UART1_DMA_Channel );
USART1_CLS_IDLEFlag();
count = RX_BUFFERSIZE - DMA_Current_Data_Transfer_Number_Get( UART1_DMA_Channel );
// for( ; count >= 0; count-- )
// {
// USART_Data_Send( USART1, RX_Buffer[ count - 1 ] );
// }
printf( "%s\n", RX_Buffer );
memset( RX_Buffer, 0, RX_BUFFERSIZE );
// DMA_Memory_Address_Config( UART1_DMA_Channel, ( uint32_t )RX_Buffer ); // 如果不重新设置DMA接收首地址 会写入刚才写入数据的尾部
DMA_Current_Data_Transfer_Number_Set( UART1_DMA_Channel, RX_BUFFERSIZE ); // 应该是调用这个函数 查数据手册->DMA部分"DMA数据传输包含三个操作...对DMATXNUMx寄存器进行量减.."->n32g430_dma.h找这个函数
// USART_DMA_Transfer_Enable( USART1, USART_DMAREQ_RX );
// DMA通道禁用即可重新加载内存地址而不是写入刚才的尾部
DMA_Channel_Enable( UART1_DMA_Channel );
}
}
main.c
#include <stdio.h>
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "function.h"
#include "FreeRTOS_Source.h"
#define countof(a) (sizeof(a) / sizeof(*(a)))
// var
TaskHandle_t task_main_handler = NULL;
int main(void)
{
Main_Init();
xTaskCreate(
TaskMain,
"TaskMain",
256,
NULL,
tskIDLE_PRIORITY + 1,
&task_main_handler
);
vTaskStartScheduler();
while (1);
return;
}
void NVIC_Configuration(void)
{
// NVIC_InitType NVIC_InitStructure;
// /* Enable the USARTy Interrupt */
// NVIC_InitStructure.NVIC_IRQChannel = USARTy_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Initializes(&NVIC_InitStructure);
// /* Enable the USARTz Interrupt */
// NVIC_InitStructure.NVIC_IRQChannel = USARTz_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Initializes(&NVIC_InitStructure);
}
void Main_Init( void )
{
mySystickInit();
my_GPIO_Init();
my_UART_Init();
my_DMA_Init();
my_NVIC_Init();
USART_DMA_Transfer_Enable( USART1, USART_DMAREQ_RX );
USART_Interrput_Enable( USART1, USART_INT_IDLEF );
// USART_Flag_Status_Get( USART1, USART_FLAG_IDLEF );
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_39812800/article/details/135040409
|