UART3.c
#include "BSP_Uart3.h"
#include "BMS.h"
/********************************************************************************************
* 变 量 声 明 *
*********************************************************************************************/
Stu_USART3_INFO Usart3_Info;
/********************************************************************************************
* 函 数 声 明 *
*********************************************************************************************/
/********************************************************************************
* 函 数 名 : Usart3_ParameterInit *
* 功 能 说 明 : UART1通信参数初始化 *
* 形 参 : baudrate:波特率 *
* 形 参 : parity:奇偶校验 *
* 形 参 : databits:数据位 *
* 形 参 : stopbits:停止位 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_ParameterInit(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits )
{
unsigned int i;
Usart3_Info.Baudrate = baudrate;
if( parity == 'N' )
{
Usart3_Info.Parity = USART_Parity_No;
}
else if ( parity == 'E' )
{
Usart3_Info.Parity = USART_Parity_Even;
}
else
{
Usart3_Info.Parity = USART_Parity_Odd;
}
if( databits == 8 )
{
Usart3_Info.DataBit = USART_WordLength_8b;
}
else
{
Usart3_Info.DataBit = USART_WordLength_9b;
}
if( stopbits == 1 )
{
Usart3_Info.StopBit = USART_StopBits_1;
}
else
{
Usart3_Info.StopBit = USART_StopBits_2;
}
Usart3_Info.RxIndex = 0;
Usart3_Info.RxHead = 0;
Usart3_Info.RxLength =0;
Usart3_Info.TxIndex = 0;
Usart3_Info.TxTail = 0;
Usart3_Info.TxLength = 0;
Usart3_Info.TxDMABusy = USART3_DMA_IDLE;
for( i=0;i<USART3_BUFLENGTH;i++)
{
Usart3_Info.RxBuf[i] = 0x00;
Usart3_Info.TxBuf[i] = 0x00;
Usart3_Info.TxDMABuf[i] = 0x00;
}
Usart3_Info.PreRxDMACounter = USART3_BUFLENGTH;
Usart3_Info.OverTime =0;
}
/********************************************************************************
* 函 数 名 : Usart3_HardwareInit *
* 功 能 说 明 : Usart3硬件初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_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 = USART3_IRQn; //USART3全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init( &NVIC_InitStructure );
//使能串口时钟: USART3对应APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能USART3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA时钟(设置TX/RX引脚)与复用时钟
//USART3发送引脚配置
GPIO_InitStructure.GPIO_Pin = USART3_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(USART3_TX_PORT, &GPIO_InitStructure);
//USART3接收引脚配置
GPIO_InitStructure.GPIO_Pin = USART3_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(USART3_RX_PORT, &GPIO_InitStructure);
//USART3参数设置
USART_InitStructure.USART_BaudRate = Usart3_Info.Baudrate;
USART_InitStructure.USART_Parity = Usart3_Info.Parity ;
USART_InitStructure.USART_WordLength = Usart3_Info.DataBit;
USART_InitStructure.USART_StopBits = Usart3_Info.StopBit;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
USART_Init(USART3, &USART_InitStructure);
USART3->BRR = 0x138;
//串口中断(DMA模式)
USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);
//启用 USART3
USART_Cmd(USART3, ENABLE);
USART_ClearFlag(USART3, USART_FLAG_TC);
}
/********************************************************************************
* 函 数 名 : Usart3_DMAInit *
* 功 能 说 明 : Usart1DMA初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_DMAInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_Initstructure;
// Configure the NVIC Preemption Priority Bits配置引脚优先级
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
//开启DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//发送DMA配置
DMA_Cmd(DMA_USART3_TX_CHANNEL, DISABLE); // 关DMA通道
DMA_DeInit(DMA_USART3_TX_CHANNEL); // 恢复缺省值
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART3->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart3_Info.TxDMABuf; // 设置发送缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST; // 设置外设为目的地址,内存缓冲区 ->外设寄存器
DMA_Initstructure.DMA_BufferSize = USART3_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_USART3_TX_CHANNEL,&DMA_Initstructure); // 开启接收DMA通道,等待接收数据
// 开启发送DMA通道中断
DMA_ITConfig(DMA_USART3_TX_CHANNEL, DMA_IT_TC, ENABLE); //DMA_IT_TC传输完成中断(transfer complete)
DMA_ITConfig(DMA_USART3_TX_CHANNEL, DMA_IT_TE, ENABLE); //DMA_IT_TE传输错误中断(transfer error)
DMA_ClearFlag(DMA_USART3_TX_FLAG); // 清除DMA所有标志
DMA_Cmd(DMA_USART3_TX_CHANNEL,DISABLE); //关DMA通道
//接收DMA配置
DMA_Cmd(DMA_USART3_RX_CHANNEL,DISABLE); //关DMA通道
DMA_DeInit(DMA_USART3_RX_CHANNEL);
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART3->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)Usart3_Info.RxBuf; // 设置接收缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 设置外设为数据源,外设寄存器 ->内存缓冲区
DMA_Initstructure.DMA_BufferSize = USART3_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_USART3_RX_CHANNEL,&DMA_Initstructure);
DMA_ITConfig(DMA_USART3_RX_CHANNEL,DMA_IT_TC,ENABLE);
DMA_ITConfig(DMA_USART3_RX_CHANNEL,DMA_IT_TE,ENABLE);
DMA_ClearFlag(DMA_USART3_RX_FLAG);
DMA_Cmd(DMA_USART3_RX_CHANNEL,ENABLE);
//开启USART3的DMA模式
USART_DMACmd(USART3,USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);
}
/********************************************************************************
* 函 数 名 : Usart3_SendtoTXbuf *
* 功 能 说 明 : Usart3发送数据到TX缓存区 *
* 形 参 : data:待发送数据首地址 *
* length:待发送数据长度
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_SendtoTXbuf( unsigned char *data, unsigned int length )
{
unsigned int i;
if( length )
{
for( i=0;i<length;i++)
{
Usart3_Info.TxLength++;
Usart3_Info.TxBuf[Usart3_Info.TxTail++]= data[i]; //循环缓冲区装载数据
if( Usart3_Info.TxTail >= USART3_BUFLENGTH )
{
Usart3_Info.TxTail -= USART3_BUFLENGTH;
}
}
}
}
/********************************************************************************
* 函 数 名 : Usart3_SendtoTXDMAbuf *
* 功 能 说 明 : Usart3发送数据到TX缓存区 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_SendtoTXDMAbuf( void )
{
unsigned int i;
if( Usart3_Info.TxLength && ( Usart3_Info.TxDMABusy == USART3_DMA_IDLE ) )
{
//有数据发送,往DMA缓冲区转移
for( i=0; i<Usart3_Info.TxLength; i++ )
{
Usart3_Info.TxDMABuf[i] = Usart3_Info.TxBuf[Usart3_Info.TxIndex++];
Usart3_Info.TxIndex = CirclePosition( Usart3_Info.TxIndex, USART3_BUFLENGTH );
}
//启动DMA数据发送
DMA_SetCurrDataCounter(DMA_USART3_TX_CHANNEL,Usart3_Info.TxLength);
Usart3_Info.TxLength = 0x00; //发送数据长度清零
Usart3_Info.TxDMABusy = USART3_DMA_BUSY;
DMA_Cmd(DMA_USART3_TX_CHANNEL, ENABLE); //开启DMA发送
}
}
/********************************************************************************
* 函 数 名 : USART3_IRQHandler *
* 功 能 说 明 : Usart3接收中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void USART3_IRQHandler(void)
{
//DMA模式
unsigned int num;
unsigned int Length;
//DMA_GetCurrDataCounter
if( USART_GetITStatus( USART3,USART_IT_IDLE ) == SET ) //整帧接收完成中断
{
DMA_Cmd(DMA_USART3_RX_CHANNEL,DISABLE); //关闭接收DMA通道
num = USART3->SR;
num = USART3->DR;
num = DMA_GetCurrDataCounter(DMA_USART3_RX_CHANNEL); //DMA接收数据后剩余缓存区间大小
//计算接收数据的长度
if( Usart3_Info.PreRxDMACounter >= num )
{
Length = Usart3_Info.PreRxDMACounter - num;
}
else
{
Length = USART3_BUFLENGTH - num + Usart3_Info.PreRxDMACounter;
}
Usart3_Info.RxLength += Length;
Usart3_Info.PreRxDMACounter = num;
Usart3_Info.RxIndex = CirclePosition( Usart3_Info.RxIndex + Length, USART3_BUFLENGTH );
USART_ClearITPendingBit(USART3, USART_IT_IDLE); //清除中断标志
DMA_Cmd(DMA_USART3_RX_CHANNEL,ENABLE); //重新开启DMA接收
}
if(USART_GetFlagStatus(USART3,USART_FLAG_ORE)==SET) //接收过载中断
{
USART_ClearFlag(USART3,USART_FLAG_ORE); //清除中断标志
USART_ReceiveData(USART3); //
}
}
/********************************************************************************
* 函 数 名 : DMA1_Channel2_IRQHandler *
* 功 能 说 明 : 发送DMA中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void DMA1_Channel2_IRQHandler(void)
{
DMA_ClearFlag(DMA1_FLAG_GL2); //清除DMA发送完成标志
DMA_Cmd(DMA_USART3_TX_CHANNEL, DISABLE); //关闭发送DMA通道
Usart3_Info.TxDMABusy = USART3_DMA_IDLE; //发送通道空闲
}
/********************************************************************************
* 函 数 名 : Usart3_Init *
* 功 能 说 明 : Usart1初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void Usart3_Init(void)
{
Usart3_ParameterInit(115200,'N',8,1);
Usart3_HardwareInit();
Usart3_DMAInit();
}
UART3.h
#ifndef _BSP_UART3_H_
#define _BSP_UART3_H_
#include "stm32f10x.h"
#define USART3_BUFLENGTH 256
#define DMA_USART3_TX_CHANNEL DMA1_Channel2
#define DMA_USART3_RX_CHANNEL DMA1_Channel3
#define DMA_USART3_TX_FLAG DMA1_FLAG_GL2 //DMA1_CHANNEL2全局中断标志
#define DMA_USART3_RX_FLAG DMA1_FLAG_GL3 //DMA1_CHANNEL3全局中断标志
#define USART3_DMA_IDLE 0x00 //USART3_DMA 空闲
#define USART3_DMA_BUSY 0x01 //USART3_DMA 忙
typedef struct
{
unsigned long Baudrate; //波特率
unsigned int Parity; //奇偶校验
unsigned int DataBit; //数据位
unsigned int StopBit; //停止位
unsigned char RxBuf[USART3_BUFLENGTH]; //接收缓存区长度
unsigned int RxIndex; //
unsigned int RxHead; //接收数据第一个字节所在位置
unsigned int RxLength; //接收数据长度
unsigned int PreRxDMACounter; //DMA剩余缓存区间大小
unsigned char TxBuf[USART3_BUFLENGTH]; //发送缓存区长度
unsigned char TxDMABuf[USART3_BUFLENGTH ]; //DMA缓冲区
unsigned int TxIndex; //
unsigned int TxTail; //发送数据第一个字节所在位置
unsigned int TxLength; //待发送数据长度
unsigned int TxDMABusy; //DMA发送忙信号
unsigned int OverTime; //通讯延时
} Stu_USART3_INFO;
//GPIO定义
#define USART3_TX_PORT GPIOB
#define USART3_TX_PIN GPIO_Pin_10
#define USART3_RX_PORT GPIOB
#define USART3_RX_PIN GPIO_Pin_11
/********************************************************************************************
* 变 量 声 明 *
*********************************************************************************************/
extern Stu_USART3_INFO Usart3_Info;
/********************************************************************************************
* 函 数 声 明 *
*********************************************************************************************/
extern void Usart3_SendtoTXbuf( unsigned char *data, unsigned int length );
extern void Usart3_SendtoTXDMAbuf( void );
extern void Usart3_Init(void);
#endif