1 usart.c
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
//void Serial_Init(void)
//{
// //使能GPIOA 以及串口1的时钟
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
//
//
// GPIO_InitTypeDef GPIO_InitStructure;;
// //初始化对应IO
// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
// 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);
//
//
// USART_InitTypeDef USART_InitStructure;
// //配置USART参数
// USART_InitStructure.USART_BaudRate=115200;
// USART_InitStructure.USART_WordLength=USART_WordLength_8b; //字节宽度8
// USART_InitStructure.USART_StopBits=USART_StopBits_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_Init(USART1,&USART_InitStructure);
//
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//
// 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
// NVIC_Init(&NVIC_InitStructure);
//
// //使能串口接收中断
// USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
// //使能串口1
// USART_Cmd(USART1,ENABLE);
//
//}
void Uart_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//使能GPIOA 以及串口1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
//初始化对应IO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
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);
//配置USART参数
USART_DeInit(USART1);
USART_InitStructure.USART_BaudRate=115200;
USART_InitStructure.USART_WordLength=USART_WordLength_8b; //字节宽度8
USART_InitStructure.USART_StopBits=USART_StopBits_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_Init(USART1,&USART_InitStructure);
//配置中断控制器
//配置中断控制器组选择
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//配制中断源
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
//配制抢占优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
//配制子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
//使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
//初始化配置NVIC
NVIC_Init(&NVIC_InitStructure);
//使能串口接收中断修改为串口总线空闲中断
// USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//使能串口1
USART_Cmd(USART1,ENABLE);
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte); //将字节数据写入数据寄存器,写入后USART自动生成时序波形
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完成
/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
}
/**
* 函 数:使用printf需要重定向的底层函数
* 参 数:保持原始格式即可,无需变动
* 返 回 值:保持原始格式即可,无需变动
*/
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch); //将printf的底层重定向到自己的发送字节函数
return ch;
}
//void DMA_SendConfig(DMA_Channel_TypeDef* DMAy_Channelx,u32 cpar,u32 cmar,u16 buf)
//{
//
// DMA_InitTypeDef DMA_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// //使能DMA时钟
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
// //配置DMA参数
//
// //配置内存地址
// DMA_InitStructure.DMA_MemoryBaseAddr=cmar;
// //配置外设地址
// DMA_InitStructure.DMA_PeripheralBaseAddr=cpar;
// //配置数据传输方向 外设作为数据传输目的地(外设作为数据源)
// DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;
// //配置数据传输大小
// DMA_InitStructure.DMA_BufferSize=buf;
// //禁止外设地址递增
// DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
// //允许内存地址是否递增
// DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
// //配置外设数据单位 8位字节传输
// DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
// //配置内存数据单位
// DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
// //配置DMA模式 单次传输(循环传输)
// DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
// //配置DMA优先级
// DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
// //配置是否使能从内存到内存传输
// DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
// //配置DMA通道初始化
// DMA_Init(DMAy_Channelx,&DMA_InitStructure);
// DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
//
// //配置串口接收中断源
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel4_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
//
// //使能DMA
DMA_Cmd(DMAy_Channelx,ENABLE);
//}
//void USART1_IRQHandler(void)
//{
//
// u8 temp=0;
// if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
// {
temp=USART_ReceiveData(USART1);
USART_SendData(USART1,temp);
// USART_ClearITPendingBit(USART1,USART_IT_RXNE);
// }
// u8 temp1=0;
// if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)
// {
// temp1=USART_ReceiveData(USART1);
// USART_SendData(USART1,temp1);
// }
//}
void DMA_SendConfig(DMA_Channel_TypeDef* DMAy_Channelx,u32 cpar,u32 cmar,u16 buf)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//使能DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//配置DMA参数
//配置内存地址
DMA_InitStructure.DMA_MemoryBaseAddr=cmar;
//配置外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr=cpar;
//配置数据传输方向 外设作为数据传输目的地(外设作为数据源)
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;
//配置数据传输大小
DMA_InitStructure.DMA_BufferSize=buf;
//禁止外设地址递增
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
//允许内存地址是否递增
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
//配置外设数据单位 8位字节传输
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
//配置内存数据单位
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
//配置DMA模式 单次传输(循环传输)
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
//配置DMA优先级
DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
//配置是否使能从内存到内存传输
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
//配置DMA通道初始化
DMA_Init(DMAy_Channelx,&DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
//配置串口接收中断源
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//使能DMA
// DMA_Cmd(DMAy_Channelx,ENABLE);
}
void DMA_ReceiveConfig(DMA_Channel_TypeDef* DMAy_Channelx,u32 cpar,u32 cmar,u16 buf)
{
DMA_InitTypeDef DMA_InitStructure;
//使能DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//配置DMA参数
//配置内存地址
DMA_InitStructure.DMA_MemoryBaseAddr=cmar;
//配置外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr=cpar;
//配置数据传输方向 外设作为数据源
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
//配置数据传输大小
DMA_InitStructure.DMA_BufferSize=buf;
//禁止外设地址递增
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
//允许内存地址是否递增
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
//配置外设数据单位 8位字节传输
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
//配置内存数据单位
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
//配置DMA模式 单次传输(循环传输)
DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
//配置DMA优先级
DMA_InitStructure.DMA_Priority=DMA_Priority_High;
//配置是否使能从内存到内存传输
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
//配置DMA通道初始化
DMA_Init(DMAy_Channelx,&DMA_InitStructure);
//使能DMA
DMA_Cmd(DMAy_Channelx,ENABLE);
}
u16 Data_LEN=100; //数据长度
u8 SendBuf[100];
u8 ReceBuf[100];
uint8_t Data_Receive_Usart;
void USART1_IRQHandler(void)
{
uint32_t temp = 0;
uint16_t i = 0;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
//USART_ClearFlag(USART3,USART_IT_IDLE);
//temp = USART1->SR; //串口状态寄存器
temp = USART1->DR; // 串口数据寄存器 (取消后会有数据丢位现象 原因待查)
DMA_Cmd(DMA1_Channel5,DISABLE); //禁用DMA接收通道
temp = Data_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); //获取DMA1通道5剩余数据
for (i = 0;i < temp;i++)
{
Data_Receive_Usart = ReceBuf[i]; //变量接收DMA通道5的数据
SendBuf[i]=Data_Receive_Usart; //将接收到的数据传到SendBuf中
DMA1_Channel4->CNDTR = (uint16_t)temp; //设置需要传输的数据量
DMA_Cmd(DMA1_Channel4, ENABLE);
}
//设置传输数据长度
DMA_SetCurrDataCounter(DMA1_Channel5,Data_LEN); //设置当前DMA1通道5中的数据量
//打开DMA
DMA_Cmd(DMA1_Channel5,ENABLE);
}
}
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_FLAG_TC4)==SET) //传输完成中断
{
DMA_ClearFlag(DMA1_FLAG_GL4); //清楚通道4全局标志位
DMA_Cmd(DMA1_Channel4, DISABLE); //关闭数据输出通道
}
}
void Test_fun(void)
{
DMA_ReceiveConfig(DMA1_Channel5,(u32)&USART1->DR,(u32)ReceBuf,100);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
DMA_SendConfig(DMA1_Channel4,(u32)&USART1->DR,(u32)SendBuf,100);
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
}
2 usart.h
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Printf(char *format, ...);
void Uart_Config(void);
void Test_fun(void);
void DMA_SendConfig(DMA_Channel_TypeDef* DMAy_Channelx,u32 cpar,u32 cmar,u16 buf);
void DMA_ReceiveConfig(DMA_Channel_TypeDef* DMAy_Channelx,u32 cpar,u32 cmar,u16 buf);
#endif
3 main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
uint8_t RxData; //定义用于接收串口数据的变量
int main(void)
{
/*串口初始化*/
// Serial_Init(); //串口初始化
Uart_Config();
//通过串口1发送单个数据
// USART_SendData(USART1,0xA0);
//检查指定的串口标志位是否设置
Test_fun();
while (1)
{
}
}