网站备案查询不了,百度信息流广告位置,很长的网站域名怎么做短,建设网站公开教学视频下载DMA串口收发数据 1、DMA串口发送数据2、DMA中断串口接收定长数据包3、串口空闲中断DMA接收不定长数据包4、串口空闲中断DMA接收不定长数据包DMA发送数据包 1、DMA串口发送数据 当串口的波特率大于115200时#xff0c;可以通过DMA1进行数据搬运#xff0c;以防止数据的丢失。如… DMA串口收发数据 1、DMA串口发送数据2、DMA中断串口接收定长数据包3、串口空闲中断DMA接收不定长数据包4、串口空闲中断DMA接收不定长数据包DMA发送数据包 1、DMA串口发送数据 当串口的波特率大于115200时可以通过DMA1进行数据搬运以防止数据的丢失。如上图所示UART1的Tx发送请求使用DMA1的通道4UART1的Rx接收数据请求使用DMA1的通道5。 ①串口发送时当UART1的发送数据寄存器TDR中没有数据时就会向DMA1的通道4申请数据搬运DMA1将缓冲区的数据搬运到TDR数据寄存器中然后串口将数据发送出去。
②串口接收时当UART1的接收数据寄存器RDR中有数据时就会向DMA1的通道5申请数据搬运DMA1将数据从RDR寄存器中搬运到缓冲区中。
【注意】数据的搬运和数据的发送的过程都不需要CPU参与CPU只参与串口UART1和DMA1通道1的配置。 ①UART.c文件的代码如下
#include UART.huint8_t Buff[Buffer_Size];//定义数据缓冲区
/*** 串口1的初始化函数*/
void UART1_Init(void)
{/* 开启串口的UART1的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);/* 开启串口的GPIO的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/* 配置串口1的引脚 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP;// 复用推挽输出GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;// 浮空输入GPIO_Init(GPIOA, GPIO_InitStruct);/* 配置串口1的模式 */USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate 115200;USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 不使用硬件流控制USART_InitStruct.USART_Mode USART_Mode_Rx | USART_Mode_Tx;// 收发模式USART_InitStruct.USART_Parity USART_Parity_No;// 无奇偶校验位USART_InitStruct.USART_StopBits USART_StopBits_1;// 1个停止位USART_InitStruct.USART_WordLength USART_WordLength_8b;// 8个数据位USART_Init(USART1, USART_InitStruct);/* 使能串口DMA发送请求 */USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);/* 使能串口1 */USART_Cmd(USART1, ENABLE);
}②UART.h文件的代码如下
#ifndef __UART_H
#define __UART_H
#include stm32f10x.h
#include stdio.h#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区void UART1_Init(void);#endif③MyDMA.c文件的代码如下
#include MyDMA.h
#include UART.h
/*** DMA1的通道4的初始化 */
void DMA1_Init(void)
{/* 1、使能DMA1的时钟 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* 2、配置DMA1的通道1 */DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); //“外设站点”的起始地址DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte;//数据宽度8位DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //外设站点地址是否自增,这里选择不自增因为搬运到数据寄存器TDR中DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)Buff; //“内存站点”起始地址DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //数据宽度8位DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //目的站点地址是否自增,自增DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralDST; //搬运方向的选择(目的地选择)这里选择内存站点---外设站点DMA_DIR_PeripheralDSTDMA_InitStruct.DMA_BufferSize 0; //传输计数器的大小代表搬运数据的个数,先置为0DMA_InitStruct.DMA_Mode DMA_Mode_Normal; //是否自动重装,这里选择不自动重装DMA_InitStruct.DMA_M2M DMA_M2M_Disable; //是否软件触发这里选择不是由硬件触发DMA_InitStruct.DMA_Priority DMA_Priority_Medium; //优先级这里选择中等DMA_Init(DMA1_Channel4,DMA_InitStruct); //配置DMA1的通道4// DMA_Cmd(DMA1_Channel4,ENABLE); //使能DMA1的通道4DMA_Cmd(DMA1_Channel4,DISABLE); //先失能DMA1的通道4
}/*** DMA1开启搬运函数*/
void UART1_DMA1_Transport(uint16_t DataNumber)
{/* 1、失能DMA1 */DMA_Cmd(DMA1_Channel4,DISABLE); /* 2、先设置传输计数器的计数值 */DMA_SetCurrDataCounter(DMA1_Channel4, DataNumber);/* 3、使能DMA1 */DMA_Cmd(DMA1_Channel4,ENABLE); /* 4、等待搬运完成 */while(!DMA_GetFlagStatus(DMA1_FLAG_TC4)); //等待DMA1通道4全部搬运完成DMA_ClearFlag(DMA1_FLAG_TC4); //手动清除标志位
}④MyDMA.h文件的代码如下
#ifndef __MyDMA_H
#define __MyDMA_H
#include stm32f10x.hvoid DMA1_Init(void);
void UART1_DMA1_Transport(uint16_t DataNumber);#endif⑤主函数main.c文件的代码如下
#include stm32f10x.h
#include Delay.h
#include UART.h
#include MyDMA.h#define DataNumber 10 //定义需要发送的数据个数int main(void)
{for(uint8_t i 0; iDataNumber; i)//先向缓冲区里面填入数据{Buff[i] i;}UART1_Init();DMA1_Init();UART1_DMA1_Transport(DataNumber); //开始搬运数据 while(1){ }
}2、DMA中断串口接收定长数据包
①UART.c文件的代码如下
#include UART.huint8_t Buff[Buffer_Size]; //定义数据缓冲区
uint16_t Length 10; //定义定长数据包长度
uint8_t Flag 0; //传输完成标志位
/*** 串口1的初始化函数*/
void UART1_Init(void)
{/* 开启串口的UART1的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);/* 开启串口的GPIO的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/* 配置串口1的引脚 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(GPIOA, GPIO_InitStruct);/* 配置串口1的模式 */USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate 115200;USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 不使用硬件流控制USART_InitStruct.USART_Mode USART_Mode_Rx | USART_Mode_Tx; // 收发模式USART_InitStruct.USART_Parity USART_Parity_No; // 无奇偶校验位USART_InitStruct.USART_StopBits USART_StopBits_1; // 1个停止位USART_InitStruct.USART_WordLength USART_WordLength_8b; // 8个数据位USART_Init(USART1, USART_InitStruct);/* 使能串口DMARx接收请求 */USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);/* 使能串口1 */USART_Cmd(USART1, ENABLE);
}/*** 串口发送多个字节的数据*/
void USART_SendArray(uint8_t *array, uint16_t len)
{/* 发送一组数据 */for (uint16_t i 0; i len; i){USART_SendChar(array[i]);}
}②UART.h文件的代码如下
#ifndef __UART_H
#define __UART_H
#include stm32f10x.h
#include stdio.h#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区
extern uint16_t Length;
extern uint8_t Flag;void UART1_Init(void);
void USART_SendArray(uint8_t *array, uint16_t len);#endif③MyDMA.c文件的代码如下
#include MyDMA.h
#include UART.h
/*** DMA1通道5的初始化*/void DMA1_Init(void)
{/* 1、使能DMA1的时钟 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* 2、配置DMA1的通道1 */DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); //外设站点的起始地址DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte;//数据宽度8位DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //外设站点地址是否自增,这里选择不自增因为搬运到数据寄存器TDR中DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)Buff; //内存站点起始地址DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //数据宽度8位DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //目的站点地址是否自增,自增DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralSRC; //搬运方向的选择(目的地选择)这里选择外设站点---内存站点DMA_DIR_PeripheralSRCDMA_InitStruct.DMA_BufferSize Length; //传输计数器的大小代表搬运数据的个数DMA_InitStruct.DMA_Mode DMA_Mode_Circular; //是否自动重装,这里选择自动重装DMA_InitStruct.DMA_M2M DMA_M2M_Disable; //是否软件触发这里选择不是由硬件触发DMA_InitStruct.DMA_Priority DMA_Priority_Medium; //优先级这里选择中等DMA_Init(DMA1_Channel5,DMA_InitStruct); //配置DMA1的通道5/* 3、使能DMA1通道5搬运完成中断和NVIC */DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel DMA1_Channel5_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority 0;NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStruct);DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的通道5
}/*** DMA1开启搬运函数*/
//void UART1_DMA1_Transport(uint16_t DataNumber)
//{
// /* 1、失能DMA1 */
// DMA_Cmd(DMA1_Channel4,DISABLE);
//
// /* 2、先设置传输计数器的计数值 */
// DMA_SetCurrDataCounter(DMA1_Channel4, DataNumber);
//
// /* 3、使能DMA1 */
// DMA_Cmd(DMA1_Channel4,ENABLE);
//
// /* 4、等待搬运完成 */
// while(!DMA_GetFlagStatus(DMA1_FLAG_TC4)); //等待通道4搬运完成
// DMA_ClearFlag(DMA1_FLAG_TC4); //手动清除标志位
//}/*** DMA1通道5传输完成的中断服务函数*/
void DMA1_Channel5_IRQHandler(void)
{if(DMA_GetFlagStatus(DMA1_FLAG_TC5)){DMA_ClearFlag(DMA1_FLAG_TC5); //清除通道5的标志位Flag 1;}
}④主函数main.c文件的代码如下
#include stm32f10x.h
#include Delay.h
#include UART.h
#include MyDMA.hint main(void)
{UART1_Init();DMA1_Init();while(1){ if(Flag){ Flag 0;USART_SendArray(Buff, Length); } }
}3、串口空闲中断DMA接收不定长数据包
①UART.c文件的代码如下
#include UART.huint8_t Buff[Buffer_Size]; //定义数据缓冲区
uint8_t Flag 0; //传输完成标志位
uint16_t Index 0; //定义接收到的数据个数
/*** 串口1的初始化函数*/
void UART1_Init(void)
{/* 开启串口的UART1的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);/* 开启串口的GPIO的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/* 配置串口1的引脚 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(GPIOA, GPIO_InitStruct);/* 配置串口1的模式 */USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate 115200;USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 不使用硬件流控制USART_InitStruct.USART_Mode USART_Mode_Rx | USART_Mode_Tx; // 收发模式USART_InitStruct.USART_Parity USART_Parity_No; // 无奇偶校验位USART_InitStruct.USART_StopBits USART_StopBits_1; // 1个停止位USART_InitStruct.USART_WordLength USART_WordLength_8b; // 8个数据位USART_Init(USART1, USART_InitStruct);/* 使能串口DMARx接收请求 */USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);/* 使能串口IDLE空闲中断和NVIC */USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority 0;NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStruct);/* 使能串口1 */USART_Cmd(USART1, ENABLE);
}/*** 串口发送一个字节的数据*/
void USART_SendChar(uint8_t ch)
{/* 发送一个字节的数据 */USART_SendData(USART1, ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET);
}/*** 串口发送一个字符串的数据*/
void USART_SendString(uint8_t *str)
{/* 发送多个字节的数据 */while (*str! \0){USART_SendChar(*str);}
}/*** 串口发送多个字节的数据*/
void USART_SendArray(uint8_t *array, uint16_t len)
{/* 发送一组数据 */for (uint16_t i 0; i len; i){USART_SendChar(array[i]);}
}/*** 对printf函数进行重定向*/
int fputc(int ch, FILE *f)
{/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET);/* 发送一个字节的数据 */USART_SendData(USART1, (uint8_t)ch);return ch;
}/*** 串口1的空闲中断服务函数*/
void USART1_IRQHandler(void)
{uint8_t Receive_Data;if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE)){ Receive_Data USART1-SR;Receive_Data USART1-DR; //清除中断标志位IDLE// Index Buffer_Size - DMA_GetCurrDataCounter(DMA1_Channel5);//获取接收到的数据个数Index Buffer_Size -(DMA1_Channel5-CNDTR); //获取接收到的数据个数Flag 1;/* 重新给DMA传输计数器设置值让第二个数据包从缓冲区第一位开始存储 */DMA_Cmd(DMA1_Channel5,DISABLE); DMA_SetCurrDataCounter(DMA1_Channel5, Buffer_Size); DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的通道5}
}②UART.h文件的代码如下
#ifndef __UART_H
#define __UART_H
#include stm32f10x.h
#include stdio.h#define Buffer_Size 256
extern uint8_t Buff[Buffer_Size];//定义数据缓冲区
extern uint8_t Flag;
extern uint16_t Index;void UART1_Init(void);
void USART_SendChar(uint8_t ch);
void USART_SendString(uint8_t *str);
void USART_SendArray(uint8_t *array, uint16_t len);#endif③MyDMA.c文件的代码如下
#include MyDMA.h
#include UART.h
/*** DMA1通道5的初始化*/void DMA1_Init(void)
{/* 1、使能DMA1的时钟 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* 2、配置DMA1的通道1 */DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); //外设站点的起始地址DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte;//数据宽度8位DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //外设站点地址是否自增,这里选择不自增因为搬运到数据寄存器TDR中DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)Buff; //内存站点起始地址DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //数据宽度8位DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //目的站点地址是否自增,自增DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralSRC; //搬运方向的选择(目的地选择)这里选择外设站点---内存站点DMA_DIR_PeripheralDSTDMA_InitStruct.DMA_BufferSize Buffer_Size; //传输计数器的大小代表搬运数据的个数DMA_InitStruct.DMA_Mode DMA_Mode_Normal; //是否自动重装,这里选择不自动重装接收一个数据包在空闲中断里面重装DMA_InitStruct.DMA_M2M DMA_M2M_Disable; //是否软件触发这里选择不是由硬件触发DMA_InitStruct.DMA_Priority DMA_Priority_Medium; //优先级这里选择中等DMA_Init(DMA1_Channel5,DMA_InitStruct); //配置DMA1的通道5DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的通道5
}④主函数main.c文件的代码如下
#include stm32f10x.h
#include Delay.h
#include UART.h
#include MyDMA.hint main(void)
{UART1_Init();DMA1_Init();while(1){ if(Flag){ Flag 0;USART_SendArray(Buff, Index); } }
}4、串口空闲中断DMA接收不定长数据包DMA发送数据包
①MyDMA.c文件的代码如下
#include MyDMA.h
#include UART.h
/*** DMA1通道5的初始化*/
void DMA1_Init(void)
{/* 1、使能DMA1的时钟 */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* 2、配置DMA1的通道5接收数据 */DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); //外设站点的起始地址DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte;//数据宽度8位DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //外设站点地址是否自增,这里选择不自增因为搬运到数据寄存器TDR中DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)Buff; //内存站点起始地址DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //数据宽度8位DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //目的站点地址是否自增,自增DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralSRC; //搬运方向的选择(目的地选择)这里选择外设站点---内存站点DMA_DIR_PeripheralSRCDMA_InitStruct.DMA_BufferSize Buffer_Size; //传输计数器的大小代表搬运数据的个数DMA_InitStruct.DMA_Mode DMA_Mode_Normal; //是否自动重装,这里选择不自动重装DMA_InitStruct.DMA_M2M DMA_M2M_Disable; //是否软件触发这里选择不是由硬件触发DMA_InitStruct.DMA_Priority DMA_Priority_Medium; //优先级这里选择中等DMA_Init(DMA1_Channel5,DMA_InitStruct); //配置DMA1的通道5DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的通道5/* 2、配置DMA1的通道4发送数据 */DMA_InitStruct.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); //外设站点的起始地址DMA_InitStruct.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte;//数据宽度8位DMA_InitStruct.DMA_PeripheralInc DMA_PeripheralInc_Disable; //外设站点地址是否自增,这里选择不自增因为搬运到数据寄存器TDR中DMA_InitStruct.DMA_MemoryBaseAddr (uint32_t)Buff; //内存站点起始地址DMA_InitStruct.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //数据宽度8位DMA_InitStruct.DMA_MemoryInc DMA_MemoryInc_Enable; //目的站点地址是否自增,自增DMA_InitStruct.DMA_DIR DMA_DIR_PeripheralDST; //搬运方向的选择(目的地选择)这里选择内存站点---外设站点DMA_DIR_PeripheralDSTDMA_InitStruct.DMA_BufferSize 0; //传输计数器的大小代表搬运数据的个数DMA_InitStruct.DMA_Mode DMA_Mode_Normal; //是否自动重装,这里选择不自动重装DMA_InitStruct.DMA_M2M DMA_M2M_Disable; //是否软件触发这里选择不是由硬件触发DMA_InitStruct.DMA_Priority DMA_Priority_Low; //优先级这里选择低DMA_Init(DMA1_Channel4,DMA_InitStruct); //配置DMA1的通道4DMA_Cmd(DMA1_Channel4,DISABLE); //失能DMA1的通道4
}/*** DMA1通道5的传输计数器重装设置*/
void DMA1_Chanael5_Count(uint16_t DataNumber)
{DMA_Cmd(DMA1_Channel5,DISABLE); DMA_SetCurrDataCounter(DMA1_Channel5, DataNumber); DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA1的通道5
}/*** DMA1通道4的传输计数器重装设置*/
void DMA1_Chanael4_Count(uint16_t DataNumber)
{DMA_Cmd(DMA1_Channel4,DISABLE); DMA_SetCurrDataCounter(DMA1_Channel4, DataNumber); DMA_Cmd(DMA1_Channel4,ENABLE); //使能DMA1的通道5
}②MyDMA.h文件的代码如下
#ifndef __MyDMA_H
#define __MyDMA_H
#include stm32f10x.hvoid DMA1_Init(void);
void DMA1_Chanael5_Count(uint16_t DataNumber);
void DMA1_Chanael4_Count(uint16_t DataNumber);#endif③UART.c文件的代码如下
#include UART.h
#include MyDMA.huint8_t Buff[Buffer_Size]; //定义数据缓冲区
uint16_t Index 0; //定义接收到的数据个数
/*** 串口1的初始化函数*/
void UART1_Init(void)
{/* 开启串口的UART1的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);/* 开启串口的GPIO的时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/* 配置串口1的引脚 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽输出GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING; // 浮空输入GPIO_Init(GPIOA, GPIO_InitStruct);/* 配置串口1的模式 */USART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate 115200;USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 不使用硬件流控制USART_InitStruct.USART_Mode USART_Mode_Rx | USART_Mode_Tx; // 收发模式USART_InitStruct.USART_Parity USART_Parity_No; // 无奇偶校验位USART_InitStruct.USART_StopBits USART_StopBits_1; // 1个停止位USART_InitStruct.USART_WordLength USART_WordLength_8b; // 8个数据位USART_Init(USART1, USART_InitStruct);/* 使能串口DMARx接收DMATx发送和请求 */USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);/* 使能串口IDLE空闲中断和NVIC */USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority 0;NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStruct);/* 使能串口1 */USART_Cmd(USART1, ENABLE);
}/*** 串口发送一个字节的数据*/
void USART_SendChar(uint8_t ch)
{/* 发送一个字节的数据 */USART_SendData(USART1, ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET);
}/*** 串口发送一个字符串的数据*/
void USART_SendString(uint8_t *str)
{/* 发送多个字节的数据 */while (*str! \0){USART_SendChar(*str);}
}/*** 串口发送多个字节的数据*/
void USART_SendArray(uint8_t *array, uint16_t len)
{/* 发送一组数据 */for (uint16_t i 0; i len; i){USART_SendChar(array[i]);}
}/*** 对printf函数进行重定向*/
int fputc(int ch, FILE *f)
{/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET);/* 发送一个字节的数据 */USART_SendData(USART1, (uint8_t)ch);return ch;
}/*** 串口1的空闲中断服务函数*/
void USART1_IRQHandler(void)
{uint8_t Receive_Data;if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE)){ Receive_Data USART1-SR;Receive_Data USART1-DR; //清除中断标志位IDLE// Index Buffer_Size - DMA_GetCurrDataCounter(DMA1_Channel5);//获取接收到的数据个数Index Buffer_Size -(DMA1_Channel5-CNDTR); //获取接收到的数据个数DMA1_Chanael4_Count(Index); //将数据发送出去DMA1_Chanael5_Count(Buffer_Size); //启动第二轮的数据接收搬运}
}④主函数main.c文件的代码如下
#include stm32f10x.h
#include Delay.h
#include UART.h
#include MyDMA.hint main(void)
{UART1_Init();DMA1_Init();while(1){ }
}