UART2.c
stu_usart2_info usart2_info;
/********************************************************************************
* 函 数 名 : usart2_parameter_init *
* 功 能 说 明 : UART1通信参数初始化 *
* 形 参 : baudrate:波特率 *
* 形 参 : parity:奇偶校验 *
* 形 参 : databits:数据位 *
* 形 参 : stopbits:停止位 *
* 返 回 值 : 无 *
*********************************************************************************/
void usart2_parameter_init(unsigned int baudrate,unsigned char parity,unsigned int databits,unsigned int stopbits)
{
unsigned int i = 0;
usart2_info.baudrate = baudrate;
if( parity == 'N' ) //无
usart2_info.parity = USART_Parity_No;
else if ( parity == 'E' ) //偶
usart2_info.parity = USART_Parity_Even;
else
usart2_info.parity = USART_Parity_Odd;
if( databits == 8 )
usart2_info.data_bit = USART_WordLength_8b;
else
usart2_info.data_bit = USART_WordLength_9b;
if( stopbits == 1 )
usart2_info.stop_bit = USART_StopBits_1;
else
usart2_info.stop_bit = USART_StopBits_2;
usart2_info.rx_index = 0;
usart2_info.rx_head = 0;
usart2_info.rx_length = 0;
usart2_info.tx_index = 0;
usart2_info.tx_tail = 0;
usart2_info.tx_length = 0;
usart2_info.tx_DMA_busy = 0;
for( i=0;i<USART2_BUFLENGTH;i++)
{
usart2_info.rx_buf[i] = 0;
usart2_info.tx_buf[i] = 0;
usart2_info.tx_DMA_buf[i] = 0;
}
usart2_info.pre_rx_DMA_counter = USART2_BUFLENGTH;
usart2_info.over_time = 0;
}
/********************************************************************************
* 函 数 名 : Usart3_HardwareInit *
* 功 能 说 明 : Usart3硬件初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void usart2_hardware_init(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 = USART2_IRQn; //USART2全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init( &NVIC_InitStructure );
//使能串口时钟: USART2对应APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能USART3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOa时钟(设置TX/RX引脚)与复用时钟
//USART2发送引脚配置
GPIO_InitStructure.GPIO_Pin = USART2_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(USART2_TX_PORT, &GPIO_InitStructure);
//USART2接收引脚配置
GPIO_InitStructure.GPIO_Pin = USART2_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(USART2_RX_PORT, &GPIO_InitStructure);
//USART2参数设置
USART_InitStructure.USART_BaudRate = usart2_info.baudrate;
USART_InitStructure.USART_Parity = usart2_info.parity;
USART_InitStructure.USART_WordLength = usart2_info.data_bit;
USART_InitStructure.USART_StopBits = usart2_info.stop_bit;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
USART_Init(USART2, &USART_InitStructure);
//串口中断(DMA模式)
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_Cmd(USART2, ENABLE);
USART_ClearFlag(USART2, USART_FLAG_TC);
}
/********************************************************************************
* 函 数 名 : Usart3_DMAInit *
* 功 能 说 明 : Usart1DMA初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void usart2_DMA_init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_Initstructure;
// Configure the NVIC Preemption Priority Bits配置引脚优先级
NVIC_InitStructure.NVIC_IRQChannel = DMA_USART2_TX_IRQ;
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_USART2_TX_CHANNEL, DISABLE); // 关DMA通道
DMA_DeInit(DMA_USART2_TX_CHANNEL); // 恢复缺省值
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART2->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)usart2_info.tx_DMA_buf; // 设置发送缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralDST; // 设置外设为目的地址,内存缓冲区 ->外设寄存器
DMA_Initstructure.DMA_BufferSize = USART2_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_USART2_TX_CHANNEL,&DMA_Initstructure); // 开启接收DMA通道,等待接收数据
// 开启发送DMA通道中断
DMA_ITConfig(DMA_USART2_TX_CHANNEL, DMA_IT_TC, ENABLE); //DMA_IT_TC传输完成中断(transfer complete)
DMA_ITConfig(DMA_USART2_TX_CHANNEL, DMA_IT_TE, ENABLE); //DMA_IT_TE传输错误中断(transfer error)
DMA_ClearFlag(DMA_USART2_TX_FLAG); // 清除DMA所有标志
DMA_Cmd(DMA_USART2_TX_CHANNEL,DISABLE); //关DMA通道
//接收DMA配置
DMA_Cmd(DMA_USART2_RX_CHANNEL, DISABLE); //关DMA通道
DMA_DeInit(DMA_USART2_RX_CHANNEL);
DMA_Initstructure.DMA_PeripheralBaseAddr =(unsigned int)(&USART2->DR); // 设置串口接收数据寄存器
DMA_Initstructure.DMA_MemoryBaseAddr = (unsigned int)usart2_info.rx_buf; // 设置发送缓冲区首地址
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 设置外设为数据源,外设寄存器 ->内存缓冲区
DMA_Initstructure.DMA_BufferSize = USART2_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_USART2_RX_CHANNEL, &DMA_Initstructure);
DMA_ITConfig(DMA_USART2_RX_CHANNEL, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA_USART2_RX_CHANNEL, DMA_IT_TE, ENABLE);
DMA_ClearFlag(DMA_USART2_RX_FLAG);
DMA_Cmd(DMA_USART2_RX_CHANNEL, ENABLE);
//开启USART2的DMA模式
USART_DMACmd(USART2, USART_DMAReq_Rx|USART_DMAReq_Tx,ENABLE);
}
/********************************************************************************
* 函 数 名 : Usart2_send_to_tx_buf
* 功 能 说 明 : Usart2发送数据到TX缓存区
* 形 参 : data:待发送数据首地址
* length:待发送数据长度
* 返 回 值 : 无
*********************************************************************************/
void usart2_send_to_tx_buf( unsigned char *data, unsigned int length )
{
unsigned int i = 0;
if( length )
{
for(i = 0; i < length; i++)
{
usart2_info.tx_length++;
usart2_info.tx_buf[usart2_info.tx_tail++] = data[i]; //循环缓冲区装载数据
if( usart2_info.tx_tail >= USART2_BUFLENGTH )
{
usart2_info.tx_tail -= USART2_BUFLENGTH;
}
}
}
}
/********************************************************************************
* 函 数 名 : Usart2_SendtoTXDMAbuf
* 功 能 说 明 : Usart2发送数据到TX缓存区
* 形 参 : 无
* 返 回 值 : 无
*********************************************************************************/
void Usart2_SendtoTXDMAbuf( void )
{
unsigned int i;
if( usart2_info.tx_length && ( usart2_info.tx_DMA_busy == USART2_DMA_IDLE ) )
{
//有数据发送,往DMA缓冲区转移
for( i = 0; i < usart2_info.tx_length; i++ )
{
usart2_info.tx_DMA_buf[i] = usart2_info.tx_buf[usart2_info.tx_index++];
usart2_info.tx_index = CirclePosition( usart2_info.tx_index, USART2_BUFLENGTH );
}
//启动DMA数据发送
DMA_SetCurrDataCounter(DMA_USART2_TX_CHANNEL, usart2_info.tx_length);
usart2_info.tx_length = 0x00; //发送数据长度清零
usart2_info.tx_DMA_busy = USART2_DMA_BUSY;
DMA_Cmd(DMA_USART2_TX_CHANNEL, ENABLE); //开启DMA发送
}
}
/********************************************************************************
* 函 数 名 : USART2_IRQHandler *
* 功 能 说 明 : Usart2接收中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void USART2_IRQHandler(void)
{
//DMA模式
unsigned int num;
unsigned int Length;
//DMA_GetCurrDataCounter
if( USART_GetITStatus( USART2,USART_IT_IDLE ) == SET ) //整帧接收完成中断
{
DMA_Cmd(DMA_USART2_RX_CHANNEL,DISABLE); //关闭接收DMA通道
num = USART2->SR;
num = USART2->DR;
num = DMA_GetCurrDataCounter(DMA_USART2_RX_CHANNEL); //DMA接收数据后剩余缓存区间大小
//计算接收数据的长度
if( usart2_info.pre_rx_DMA_counter >= num )
{
Length = usart2_info.pre_rx_DMA_counter - num;
}
else
{
Length = USART2_BUFLENGTH - num + usart2_info.pre_rx_DMA_counter;
}
usart2_info.rx_length += Length;
usart2_info.pre_rx_DMA_counter = num;
usart2_info.rx_index = CirclePosition( usart2_info.rx_index + Length, USART2_BUFLENGTH );
USART_ClearITPendingBit(USART2, USART_IT_IDLE); //清除中断标志
DMA_Cmd(DMA_USART2_RX_CHANNEL,ENABLE); //重新开启DMA接收
}
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET) //接收过载中断
{
USART_ClearFlag(USART2,USART_FLAG_ORE); //清除中断标志
USART_ReceiveData(USART2); //
}
}
/********************************************************************************
* 函 数 名 : DMA1_Channel7_IRQHandler *
* 功 能 说 明 : 发送DMA中断处理函数 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void DMA1_Channel7_IRQHandler(void)
{
DMA_ClearFlag(DMA_USART2_TX_FLAG); //清除DMA发送完成标志
DMA_Cmd(DMA_USART2_TX_CHANNEL, DISABLE); //关闭发送DMA通道
usart2_info.tx_DMA_busy = USART2_DMA_IDLE; //发送通道空闲
}
/********************************************************************************
* 函 数 名 : Usart1_Init *
* 功 能 说 明 : Usart1初始化 *
* 形 参 : 无 *
* 返 回 值 : 无 *
*********************************************************************************/
void usart2_init(void)
{
usart2_parameter_init(115200,'N',8,1);
usart2_hardware_init();
usart2_DMA_init();
}
UART2.h
#ifndef _BSP_UART2_H_
#define _BSP_UART2_H_
#include "stm32f10x.h"
#define USART2_BUFLENGTH 256
#define DMA_USART2_TX_CHANNEL DMA1_Channel7
#define DMA_USART2_RX_CHANNEL DMA1_Channel6
#define DMA_USART2_TX_FLAG DMA1_FLAG_GL7 //DMA1_CHANNEL2全局中断标志
#define DMA_USART2_RX_FLAG DMA1_FLAG_GL6 //DMA1_CHANNEL3全局中断标志
#define DMA_USART2_TX_IRQ DMA1_Channel7_IRQn
#define DMA_USART2_RX_IRQ DMA1_Channel6_IRQn
#define USART2_DMA_IDLE 0x00 //USART3_DMA 空闲
#define USART2_DMA_BUSY 0x01 //USART3_DMA 忙
typedef struct
{
unsigned long baudrate; //波特率
unsigned int parity; //奇偶校验
unsigned int data_bit; //数据位
unsigned int stop_bit; //停止位
unsigned char rx_buf[USART2_BUFLENGTH]; //接收缓存区长度
unsigned int rx_index; //
unsigned int rx_head; //接收数据第一个字节所在位置
unsigned int rx_length; //接收数据长度
unsigned int pre_rx_DMA_counter; //DMA剩余缓存区间大小
unsigned char tx_buf[USART2_BUFLENGTH]; //发送缓存区长度
unsigned char tx_DMA_buf[USART2_BUFLENGTH ]; //DMA缓冲区
unsigned int tx_index; //
unsigned int tx_tail; //发送数据第一个字节所在位置
unsigned int tx_length; //待发送数据长度
unsigned int tx_DMA_busy; //DMA发送忙信号
unsigned int over_time; //通讯延时
}stu_usart2_info;
//GPIO定义
#define USART2_TX_PORT GPIOA
#define USART2_TX_PIN GPIO_Pin_2
#define USART2_RX_PORT GPIOA
#define USART2_RX_PIN GPIO_Pin_3
extern stu_usart2_info usart2_info;
void usart2_send_to_tx_buf( unsigned char *data, unsigned int length );
void Usart2_SendtoTXDMAbuf( void );
void usart2_init(void);
#endif