宏定义
/*******************************************************/
//DMA发送
#define DEBUG_USART_DR_BASE (USART1_BASE+0x04)
#define SEND_BUFF_SIZE 64 //发送的数据量
#define DEBUG_USART_DMA_Tx_CLK RCC_AHB1Periph_DMA2
#define DEBUG_USART_DMA_Tx_CHANNEL DMA_Channel_4
#define DEBUG_USART_DMA_Tx_STREAM DMA2_Stream7
#define DEBUG_USART_DMA_Tx_IRQ DMA2_Stream7_IRQn
//DMA接收
#define DEBUG_USART_DR_BASE (USART1_BASE+0x04)
#define RECEIVE_BUFF_SIZE 64 //接收的数据量
#define DEBUG_USART_DMA_Rx_CLK RCC_AHB1Periph_DMA2
#define DEBUG_USART_DMA_Rx_CHANNEL DMA_Channel_4
#define DEBUG_USART_DMA_Rx_STREAM DMA2_Stream5
#define DEBUG_USART_DMA_Rx_IRQ DMA2_Stream5_IRQn
//USART
#define DEBUG_USART USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_BAUDRATE 115200
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_RX_PIN GPIO_Pin_10
#define DEBUG_USART_RX_AF GPIO_AF_USART1
#define DEBUG_USART_RX_SOURCE GPIO_PinSource10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_TX_PIN GPIO_Pin_9
#define DEBUG_USART_TX_AF GPIO_AF_USART1
#define DEBUG_USART_TX_SOURCE GPIO_PinSource9
#define DEBUG_USART_IRQHandler USART1_IRQHandler
#define DEBUG_USART_IRQ USART1_IRQn
/******************************
函数配置
/*******************************************************/
void Receive_DataPack(void);
void test(void);
void NVIC_Config(void){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_DMA_Tx_IRQ; //中断类型:DMA2数据流7中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //开启中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6; //中断抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中断响应优先级
NVIC_Init(&NVIC_InitStructure); //初始化中断
}
/*DMA_Tx*/
uint8_t SendBuff[SEND_BUFF_SIZE];
void USART1_DMA_Tx_Config(void) {
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(DEBUG_USART_DMA_Tx_CLK, ENABLE);//开启DMA时钟
DMA_DeInit(DEBUG_USART_DMA_Tx_STREAM);// 复位初始化DMA数据流
/* 确保DMA数据流复位完成 */
while (DMA_GetCmdStatus(DEBUG_USART_DMA_Tx_STREAM) != DISABLE) { }
DMA_InitStructure.DMA_Channel = DEBUG_USART_DMA_Tx_CHANNEL; //sart1 tx对应dma2,通道4,数据流7
DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_USART_DR_BASE; //设置DMA源:串口数据寄存器地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SendBuff; //内存地址(要传输的变量的指针)
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //方向:从内存到外设
DMA_InitStructure.DMA_BufferSize = SEND_BUFF_SIZE; //传输大小DMA_BufferSize=SENDBUFF_SIZE
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; //内存数据单位 8bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA模式:不断循环
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级:中
/*禁用FIFO*/
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发传输 16个节拍
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发传输 1个节拍
DMA_Init(DEBUG_USART_DMA_Tx_STREAM, &DMA_InitStructure); //配置DMA2的数据流7
DMA_Cmd(DEBUG_USART_DMA_Tx_STREAM, ENABLE);//使能DMA
while(DMA_GetCmdStatus(DEBUG_USART_DMA_Tx_STREAM) != ENABLE) { }// 等待DMA数据流有效
}
/*DMA_Rx*/
uint8_t ReceiveBuff[RECEIVE_BUFF_SIZE];
void USART1_DMA_Rx_Config(void) {
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(DEBUG_USART_DMA_Rx_CLK, ENABLE);//开启DMA时钟
DMA_DeInit(DEBUG_USART_DMA_Rx_STREAM);// 复位初始化DMA数据流
while (DMA_GetCmdStatus(DEBUG_USART_DMA_Rx_STREAM) != DISABLE) { }// 确保DMA数据流复位完成
DMA_InitStructure.DMA_Channel = DEBUG_USART_DMA_Rx_CHANNEL; //sart1 tx对应dma2,通道4,数据流7
DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_USART_DR_BASE; //设置DMA源:串口数据寄存器地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ReceiveBuff; //内存地址(要传输的变量的指针)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //方向:从内存到外设
DMA_InitStructure.DMA_BufferSize = RECEIVE_BUFF_SIZE; //传输大小DMA_BufferSize=SENDBUFF_SIZE
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; //内存数据单位 8bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA模式:不断循环
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级:中
/*禁用FIFO*/
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发传输 16个节拍
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发传输 1个节拍
DMA_Init(DEBUG_USART_DMA_Rx_STREAM, &DMA_InitStructure); //配置DMA2的数据流7
DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM, ENABLE);//使能DMA
while(DMA_GetCmdStatus(DEBUG_USART_DMA_Rx_STREAM) != ENABLE) { }// 等待DMA数据流有效
}
void USART_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK|DEBUG_USART_TX_GPIO_CLK,ENABLE);
RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置Tx引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
/* 配置Rx引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,DEBUG_USART_RX_SOURCE,DEBUG_USART_RX_AF); /* 连接 PXx 到 USARTx_Tx*/
GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,DEBUG_USART_TX_SOURCE,DEBUG_USART_TX_AF); /* 连接 PXx 到 USARTx__Rx*/
/* 配置串DEBUG_USART 模式 */
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;/* 波特率设置:DEBUG_USART_BAUDRATE */
USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* 字长(数据位+校验位):8 */
USART_InitStructure.USART_StopBits = USART_StopBits_1; /* 停止位:1个停止位 */
USART_InitStructure.USART_Parity = USART_Parity_No; /* 校验位选择:不使用校验 */
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* 硬件流控制:不使用硬件流 */
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* USART模式控制:同时使能接收和发送 */
/* 完成USART初始化配置 */
USART_Init(DEBUG_USART, &USART_InitStructure);
//中断设置
USART_ITConfig(DEBUG_USART,USART_IT_TC,DISABLE); //关闭传输完成中断
USART_ITConfig(DEBUG_USART,USART_IT_RXNE,DISABLE); //关闭串口接收中断
USART_ITConfig(DEBUG_USART,USART_IT_TXE,DISABLE); //关闭发送寄存器空中断
USART_ITConfig(DEBUG_USART,USART_IT_IDLE,ENABLE); //开启空闲中断
USART_Cmd(DEBUG_USART, ENABLE); //使能串口
NVIC_Config();
USART1_DMA_Tx_Config();
USART1_DMA_Rx_Config();
USART_DMACmd(DEBUG_USART,USART_DMAReq_Tx,ENABLE); //开启DMA发模式
USART_DMACmd(DEBUG_USART,USART_DMAReq_Rx,ENABLE); //开启DMA收模式
USART_ClearFlag(DEBUG_USART,USART_FLAG_TC);
}
/*******************************************************/
//发送中断函数
void DMA2_Stream7_IRQHandler(void){
if(DMA_GetITStatus(DMA2_Stream7,DMA_IT_TCIF7) !=RESET){ //判断中断类型
DMA_Cmd(DMA2_Stream7,DISABLE); //关闭DMA传输
DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7); //清除传输完成标志位
DMA_SetCurrDataCounter(DMA2_Stream7,SEND_BUFF_SIZE);
USART_ITConfig(DEBUG_USART,USART_IT_TC,ENABLE); //开启串口传输完成中断,发送最后两个字节
}
}
//串口中断函数
void USART1_IRQHandler(void){
if(USART_GetITStatus(DEBUG_USART,USART_IT_IDLE)!=RESET)
{
Receive_DataPack(); //接收数据
USART_ReceiveData( DEBUG_USART );// 清除空闲中断标志位
}
}
//接收数据并处理
static u16 Recv_Size = 0; //获取接收大小
void Receive_DataPack(void)
{
int i=0;
DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM, DISABLE); /* 关闭DMA ,防止干扰,数据尚未处理 */
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5); /* 清DMA标志位 */
Recv_Size = RECEIVE_BUFF_SIZE - DMA_GetCurrDataCounter(DEBUG_USART_DMA_Rx_STREAM);//得到接收字节长度
// for(i=0;i<Recv_Size;i++){printf("%2X ",ReceiveBuff[i]);}
DMA_SetCurrDataCounter(DEBUG_USART_DMA_Rx_STREAM,RECEIVE_BUFF_SIZE); /* 重新赋值计数值,必须大于等于最大可能接收到的数据帧数目 */
DMA_Cmd(DEBUG_USART_DMA_Rx_STREAM,ENABLE); /* 此处应该在处理完数据再打开,如在 DataPack_Process() 打开*/
}
/*******************************************************/
/*******************************************************/
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USART, (uint8_t) ch);/* 发送一个字节数据到串口 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET); /* 等待发送完毕 */
return (ch);
}
///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USART);
}
extern uint8_t SendBuff[SENDBUFF_SIZE];//给SendBuff[]赋值时,需要在前面调用串口函数里面的SendBuff[]
USART_DMACmd(DEBUG_USART, USART_DMAReq_Tx, ENABLE); //USART1 向 DMA发出TX请求