UART1.c
/********************************************************************************************
* 变 量 声 明 *
*********************************************************************************************/
Stu_USART1_INFO Usart1_Info;
/********************************************************************************************
* 函 数 声 明 *
*********************************************************************************************/
unsigned int CirclePosition( unsigned int position, unsigned int length )
{
if( position >= length )
position -= length;
return position;
}
/********************************************************************************
* 函 数 名 : Usart1_ParameterInit *
* 功 能 说 明 : UART1通信参数初始化 *
* 形 参 : baudrate:波特率 *
* 形 参 : parity:奇偶校验 *
* 形 参 : databits:数据位 *
* 形 参 : stopbits:停止位 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_ParameterInit(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits )
{
unsigned int i;
Usart1_Info.Baudrate = baudrate;
if( parity == 'N' )
{
Usart1_Info.Parity = USART_Parity_No;
}
else if ( parity == 'E' )
{
Usart1_Info.Parity = USART_Parity_Even;
}
else
{
Usart1_Info.Parity = USART_Parity_Odd;
}
if( databits == 8 )
{
Usart1_Info.DataBit = USART_WordLength_8b;
}
else
{
Usart1_Info.DataBit = USART_WordLength_9b;
}
if( stopbits == 1 )
{
Usart1_Info.StopBit = USART_StopBits_1;
}
else
{
Usart1_Info.StopBit = USART_StopBits_2;
}
Usart1_Info.RxIndex = 0;
Usart1_Info.RxHead = 0;
Usart1_Info.RxLength =0;
Usart1_Info.TxIndex = 0;
Usart1_Info.TxTail = 0;
Usart1_Info.TxLength = 0;
Usart1_Info.TxDMABusy = USART1_DMA_IDLE;
for( i=0;i<USART1_BUFLENGTH;i++)
{
Usart1_Info.RxBuf[i] = 0x00;
Usart1_Info.TxBuf[i] = 0x00;
Usart1_Info.TxDMABuf[i] = 0x00;
}
Usart1_Info.PreRxDMACounter = USART1_BUFLENGTH;
Usart1_Info.OverTime =0;
}
/********************************************************************************
* 函 数 名 : Usart1_HardwareInit *
* 功 能 说 明 : Usart1硬件初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_HardwareInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //中断向量初始化结构体
GPIO_InitTypeDef GPIO_InitStructure; //GPIO初始化结构体
USART_InitTypeDef USART_InitStructure; //USART初始化结构体
// Configure the NVIC Preemption Priority Bits
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置优先级组
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //USART1全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init( &NVIC_InitStructure );
//使能串口时钟: USART1对应APB1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA时钟(设置TX/RX引脚)与复用时钟
//USART1发送引脚配置
GPIO_InitStructure.GPIO_Pin = USART1_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(USART1_TX_PORT, &GPIO_InitStructure);
//USART1接收引脚配置
GPIO_InitStructure.GPIO_Pin = USART1_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(USART1_RX_PORT, &GPIO_InitStructure);
//USART1参数设置
USART_InitStructure.USART_BaudRate = Usart1_Info.Baudrate;
USART_InitStructure.USART_Parity = Usart1_Info.Parity ;
USART_InitStructure.USART_WordLength = Usart1_Info.DataBit;
USART_InitStructure.USART_StopBits = Usart1_Info.StopBit;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
USART1->BRR = 0x271;
//串口空闲中断(DMA模式)
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//启用 USART1
USART_Cmd(USART1, ENABLE);
USART_ClearFlag(USART1, USART_FLAG_TC);
}
/********************************************************************************
* 函 数 名 : Usart1_DMAInit *
* 功 能 说 明 : Usart1DMA初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_DMAInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_Initstructure;
// Configure the NVIC Preemption Priority Bits配置引脚优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
//开启DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//发送DMA配置
DMA_Cmd(DMA_USART1_TX_CHANNEL, DISABLE); // 关DMA通道
DMA_DeInit(DMA_USART1_TX_CHANNEL); // 恢复缺省值
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART1->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart1_Info.TxDMABuf; // 设置发送缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST; // 设置外设为目的地址,内存缓冲区 ->外设寄存器
DMA_Initstructure.DMA_BufferSize = USART1_BUFLENGTH; // 需要最大可能接收到的字节数
DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不做增加调整,调整不调整是DMA自动实现的
DMA_Initstructure.DMA_MemoryInc =DMA_MemoryInc_Enable; // 内存缓冲区地址增加调整
DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节
DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存数据宽度8位,1个字节
DMA_Initstructure.DMA_Mode = DMA_Mode_Normal; // 循环传输模式:DMA_Mode_Circular; 单次传输模式DMA_Mode_Normal;
DMA_Initstructure.DMA_Priority = DMA_Priority_High; // 优先级设置,设置为高
DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;
//启动发送DMA
DMA_Init(DMA_USART1_TX_CHANNEL,&DMA_Initstructure); // 开启接收DMA通道,等待接收数据
// 开启发送DMA通道中断
DMA_ITConfig(DMA_USART1_TX_CHANNEL, DMA_IT_TC, ENABLE); //DMA_IT_TC传输完成中断(transfer complete)
DMA_ITConfig(DMA_USART1_TX_CHANNEL, DMA_IT_TE, ENABLE); //DMA_IT_TE传输错误中断(transfer error)
DMA_ClearFlag(DMA_USART1_TX_FLAG); // 清除DMA所有标志
DMA_Cmd(DMA_USART1_TX_CHANNEL,DISABLE); //启用DMA通道
//接收DMA配置
DMA_Cmd(DMA_USART1_RX_CHANNEL,DISABLE); //关DMA通道
DMA_DeInit(DMA_USART1_RX_CHANNEL);
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART1->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart1_Info.RxBuf; // 设置发送缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 设置外设为数据源,外设寄存器 ->内存缓冲区
DMA_Initstructure.DMA_BufferSize = USART1_BUFLENGTH; // 需要最大可能接收到的字节数
DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不做增加调整,调整不调整是DMA自动实现的
DMA_Initstructure.DMA_MemoryInc =DMA_MemoryInc_Enable; // 内存缓冲区地址增加调整
DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节
DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存数据宽度8位,1个字节
DMA_Initstructure.DMA_Mode = DMA_Mode_Circular; // 循环传输模式:DMA_Mode_Circular; 单次传输模式DMA_Mode_Normal;
DMA_Initstructure.DMA_Priority = DMA_Priority_High; // 优先级设置,设置为高
DMA_Initstructure.DMA_M2M = DMA_M2M_Disable; //关闭存储器到存储器传输模式
//开启接收DMA通道
DMA_Init(DMA_USART1_RX_CHANNEL,&DMA_Initstructure);
DMA_ITConfig(DMA_USART1_RX_CHANNEL,DMA_IT_TC,ENABLE);
DMA_ITConfig(DMA_USART1_RX_CHANNEL,DMA_IT_TE,ENABLE);
DMA_ClearFlag(DMA_USART1_RX_FLAG);
DMA_Cmd(DMA_USART1_RX_CHANNEL,ENABLE);
//开启USART1的DMA模式
USART_DMACmd(USART1,USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);
}
/********************************************************************************
* 函 数 名 : Usart1_SendtoTXbuf *
* 功 能 说 明 : Usart1发送数据到TX缓存区 *
* 形 参 : data:待发送数据首地址 *
* length:待发送数据长度
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_SendtoTXbuf( unsigned char *data, unsigned int length )
{
unsigned int i;
if( length )
{
for( i=0;i<length;i++)
{
Usart1_Info.TxLength++;
Usart1_Info.TxBuf[Usart1_Info.TxTail++]= data[i]; //循环缓冲区装载数据
if( Usart1_Info.TxTail >= USART1_BUFLENGTH )
{
Usart1_Info.TxTail -= USART1_BUFLENGTH;
}
}
}
}
/********************************************************************************
* 函 数 名 : Usart1_SendtoTXDMAbuf *
* 功 能 说 明 : Usart1发送数据到TX缓存区 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_SendtoTXDMAbuf( void )
{
unsigned int i;
if( Usart1_Info.TxLength && ( Usart1_Info.TxDMABusy == USART1_DMA_IDLE ) )
{
//有数据发送,往DMA缓冲区转移
for( i=0; i<Usart1_Info.TxLength; i++ )
{
Usart1_Info.TxDMABuf[i] = Usart1_Info.TxBuf[Usart1_Info.TxIndex++];
Usart1_Info.TxIndex = CirclePosition( Usart1_Info.TxIndex, USART1_BUFLENGTH );
}
//启动DMA数据发送
DMA_SetCurrDataCounter(DMA_USART1_TX_CHANNEL,Usart1_Info.TxLength);
Usart1_Info.TxLength = 0x00;
Usart1_Info.TxDMABusy = USART1_DMA_BUSY;
DMA_Cmd(DMA_USART1_TX_CHANNEL, ENABLE);
}
}
/********************************************************************************
* 函 数 名 : USART1_IRQHandler *
* 功 能 说 明 : Usart1中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void USART1_IRQHandler(void)
{
//DMA模式
unsigned int num;
unsigned int Length;
//DMA_GetCurrDataCounter
if( USART_GetITStatus( USART1,USART_IT_IDLE ) == SET ) //整帧接收完成中断
{
DMA_Cmd(DMA_USART1_RX_CHANNEL,DISABLE); //关闭接收DMA通道
//num = USART1->SR;
num = USART1->DR; //读SR后读DR清USART_IT_IDLE标志
num = DMA_GetCurrDataCounter(DMA_USART1_RX_CHANNEL); //DMA接收数据后剩余缓存区间大小
//计算接收数据的长度
if( Usart1_Info.PreRxDMACounter >= num )
{
Length = Usart1_Info.PreRxDMACounter - num;
}
else
{
Length = USART1_BUFLENGTH - num + Usart1_Info.PreRxDMACounter;
}
Usart1_Info.RxLength += Length;
Usart1_Info.PreRxDMACounter = num;
Usart1_Info.RxIndex = CirclePosition( Usart1_Info.RxIndex + Length, USART1_BUFLENGTH );
USART_ClearITPendingBit(USART1, USART_IT_IDLE); //清除中断标志
DMA_Cmd(DMA_USART1_RX_CHANNEL,ENABLE); //重新开启DMA接收
}
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)
{
USART_ClearFlag(USART1,USART_FLAG_ORE); //读SR
USART_ReceiveData(USART1); //读DR
}
}
/********************************************************************************
* 函 数 名 : DMA1_Channel2_IRQHandler *
* 功 能 说 明 : 发送DMA中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void DMA1_Channel4_IRQHandler(void)
{
DMA_ClearFlag(DMA1_FLAG_GL4); //清除DMA发送完成标志
DMA_Cmd(DMA_USART1_TX_CHANNEL, DISABLE); //关闭发送DMA通道
Usart1_Info.TxDMABusy = USART1_DMA_IDLE; //发送通道空闲
}
/********************************************************************************
* 函 数 名 : Usart1_Init *
* 功 能 说 明 : Usart1初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart1_Init(void)
{
Usart1_ParameterInit(115200,'N',8,1);
Usart1_HardwareInit();
Usart1_DMAInit();
}
UART1.h
#ifndef _BSP_UART1_H_
#define _BSP_UART1_H_
#include "stm32f10x.h"
#define USART1_BUFLENGTH 256
#define DMA_USART1_RX_CHANNEL DMA1_Channel5
#define DMA_USART1_TX_CHANNEL DMA1_Channel4
#define DMA_USART1_RX_FLAG DMA1_FLAG_GL5 //DMA1_CHANNEL5全局中断标志
#define DMA_USART1_TX_FLAG DMA1_FLAG_GL4 //DMA1_CHANNEL4全局中断标志
#define USART1_DMA_IDLE 0x00 //USART3_DMA 空闲
#define USART1_DMA_BUSY 0x01 //USART3_DMA 忙
typedef struct
{
unsigned long Baudrate; //波特率
unsigned int Parity; //奇偶校验
unsigned int DataBit; //数据位
unsigned int StopBit; //停止位
unsigned char RxBuf[USART1_BUFLENGTH]; //接收缓存区长度
unsigned int RxIndex; //
unsigned int RxHead; //
unsigned int RxLength; //接收数据长度
unsigned int PreRxDMACounter; //DMA剩余缓存区间大小
unsigned char TxBuf[USART1_BUFLENGTH]; //发送缓存区长度
unsigned char TxDMABuf[USART1_BUFLENGTH ]; //DMA缓冲区
unsigned int TxIndex; //
unsigned int TxTail; //
unsigned int TxLength; //待发送数据长度
unsigned int TxDMABusy; //DMA发送忙信号
unsigned int OverTime; //通讯延时
} Stu_USART1_INFO;
//GPIO定义
#define USART1_TX_PORT GPIOA
#define USART1_TX_PIN GPIO_Pin_9
#define USART1_RX_PORT GPIOA
#define USART1_RX_PIN GPIO_Pin_10
/********************************************************************************************
* 变 量 声 明 *
*********************************************************************************************/
extern Stu_USART1_INFO Usart1_Info;
/********************************************************************************************
* 函 数 声 明 *
*********************************************************************************************/
extern void Usart1_SendtoTXbuf( unsigned char *data, unsigned int length );
extern void Usart1_SendtoTXDMAbuf( void );
extern void Usart1_Init(void);
extern unsigned int CirclePosition( unsigned int position, unsigned int length );
#endif