bsp_DMAusart1.h
#ifndef __BSP_DMAUSART1_H
#define __BSP_DMAUSART1_H
//-------------------------------------------------------------------
#include "stm32f10x.h"
#include <string.h>
//-------------------------------------------------------------------
#define USART1_REC_LEN 58 //定义最大接收字节数 58
typedef struct
{
uint8_t Tx_buf[USART1_REC_LEN]; //发送缓冲区
uint8_t Tx_len; //发送长度
uint8_t Rx_buf[USART1_REC_LEN]; //接收缓冲区
uint8_t Rx_len; //接收长度
uint8_t Rx_end_flag; //接收完成标志
uint8_t Rx_time_start; //计时启动标志
uint16_t Rx_time; //1祯数据接收时长(mSec)
}USART1_DEF;
extern USART1_DEF OneUART;
//-------------------------------------------------------------------
void USART1_Init(uint32_t BAND,uint8_t *SendAddres,uint8_t *RecAddres,uint8_t len);
void DMA_USART1RxTx_Init(uint8_t *SendAd,uint8_t *RecAddres,uint8_t len);
void NVIC_USART1_Configuration(void);
void USART1_SendChar(u8 t);
void USART_printf(USART_TypeDef* USARTx, uint8_t *Data,...);
void USART1_SendString(void* buffer, uint16_t size);
void USART1_Encryption_SendString(void* buffer, uint16_t size);
uint16_t USART1_DMASendString(void* buffer, uint16_t size);
uint16_t USART1_Encryption_DMASendString(void* buffer, uint16_t size);
#endif /* __USART1_H */
bsp_DMAusart1.c
#include "bsp_DMAusart1.h"
USART1_DEF OneUART;
/**
* @brief USART1初始化
* @param BAND,波特率(2400,4800,9600,38400,115200)
* Send_pf,发送数据缓冲区
* Rec_pf,接收数据缓冲区
* buf_len,接收数据缓冲区长度
* @retval 无
*/
void USART1_Init(uint32_t BAND,uint8_t *Send_pf,uint8_t *Rec_pf,uint8_t buf_len)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOB, ENABLE);
/* USART1 GPIO config */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能端口重映射
/* Configure USART1 Tx (PB6) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure USART1 Rx (PB7) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* RS485,Tx/Rx Control PB5 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = BAND;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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);
USART_Cmd(USART1, ENABLE);
USART_ClearFlag(USART1, USART_FLAG_TC); //清发送完成标志
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); //开启空闲中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断
USART_ITConfig(USART1, USART_IT_TC, ENABLE); //开启发送完成中断
NVIC_USART1_Configuration();
DMA_USART1RxTx_Init(Send_pf,Rec_pf,buf_len);//DMA初始化
}
/**
* @brief 配置USART1中断
* @param
* @retval 无
*/
static void NVIC_USART1_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //开启接收完成中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;//开启发送完成中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief DMA_USART1初始化
* @param Send_pf,发送数据缓冲区
* Rec_pf,接收数据缓冲区
* buf_len,接收数据缓冲区长度
* @retval 无
*/
static void DMA_USART1RxTx_Init(uint8_t *Send_pf,uint8_t *Rec_pf,uint8_t buf_len)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_Cmd(DMA1_Channel5,DISABLE); //关闭DMA
DMA_DeInit(DMA1_Channel5); //恢复默认
DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&USART1->DR; //设置串口发送数据寄存器
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)Rec_pf; //设置发送缓冲区首地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //设置外设位目标,内存缓冲区 <- 外设寄存器
DMA_InitStructure.DMA_BufferSize=buf_len; //需要发送的字节数,这里其实可以设置为0,因为在实际要发送的时候,会重新设置次值
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设字节宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存字节宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式
DMA_Init(DMA1_Channel5,&DMA_InitStructure); //配置DMA1的6通道
DMA_Cmd(DMA1_Channel5,ENABLE); //使能DMA
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr= (u32)&USART1->DR; //初始化外设地址
DMA_InitStructure.DMA_MemoryBaseAddr=(u32)Send_pf; //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据来源
DMA_InitStructure.DMA_BufferSize=0; //发送长度为0
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设字节宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存字节宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式
DMA_Init(DMA1_Channel4,&DMA_InitStructure); //配置DMA1的7通道
DMA_Cmd(DMA1_Channel4,ENABLE); //使能DMA
USART_ITConfig(USART1, USART_DMAReq_Tx, ENABLE); //开启中断USART_DMAReq_Tx
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //开启接收接收
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //开启接收发送
// DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); //配置DMA发送完成后产生中断
}
/**
* @brief USART1_DMA发送完成中断
* @param 无
* @retval 无
*/
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)
{//发送完成中断
DMA_ClearFlag(DMA1_FLAG_TC4);
//GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
}
/**
* @brief USART1串口接收中断
* @param 无
* @retval 无
*/
void USART1_IRQHandler(void) //串口1中断服务程序
{
static uint8_t LEN=0;
uint8_t Clear=Clear,tmp;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{//接收中断
OneUART.Rx_buf[LEN++]= USART1->DR; //读取接收到的数据
LEN= (LEN < USART1_REC_LEN)?LEN:0;
}else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{//空闲中断,1桢数据接收完毕
Clear=USART1->SR; //读SR寄存器
Clear=USART1->DR; //读DR寄存器,(先读SR,再读DR就是清除IDLE标志中断)
OneUART.Rx_end_flag = 1; //接收完成标志
DMA_Cmd(DMA1_Channel5,DISABLE);
OneUART.Rx_len=USART1_REC_LEN-DMA_GetCurrDataCounter(DMA1_Channel5);
DMA_SetCurrDataCounter(DMA1_Channel5,USART1_REC_LEN); //设置DMA缓冲区长度
DMA_Cmd(DMA1_Channel5,ENABLE);
}else if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{//发送完成中断
USART_ClearITPendingBit(USART1, USART_IT_TC); //清除USART1发送完成中断标志
DMA_ClearFlag(DMA1_FLAG_TC4); //清零标志位
GPIO_ResetBits(GPIOB,GPIO_Pin_5); //发送完成,等待接收数据
}
}
/**
* @brief DMA_USART1数据发送
* @param buffer,发送数据地址
* size,发送数据长度
* @retval size
*/
uint16_t USART1_DMASendString(void* buffer, uint16_t size)
{
if(!size) return 0; //判断长度是否有效
while(DMA_GetCurrDataCounter(DMA1_Channel4)); //检查DMA通道内是否还有数据
if(buffer) //发送数据拷贝到发送缓存区
memcpy(OneUART.Tx_buf, buffer,(size > 1024?1024:size));
DMA_Cmd(DMA1_Channel4, DISABLE); //DMA发送数据要先关闭,设置发送数据长度 开启DMA
DMA1_Channel4->CNDTR = size; //设置发送长度
GPIO_SetBits(GPIOB,GPIO_Pin_5);
DMA_Cmd(DMA1_Channel4, ENABLE); //启动DMA发送
return size;
}
/**
* @brief DMA_USART1加密数据发送
* @param buffer,发送数据地址
* size,发送数据长度
* @retval size
*/
uint16_t USART1_Encryption_DMASendString(void* buffer, uint16_t size)
{
if(!size) return 0; //判断长度是否有效
while(DMA_GetCurrDataCounter(DMA1_Channel4)); //检查DMA通道内是否还有数据
if(buffer) //发送数据拷贝到发送缓存区
{
//encryption(buffer,size);//使能加密
memcpy(OneUART.Tx_buf, buffer,(size > 1024?1024:size));
}
DMA_Cmd(DMA1_Channel4, DISABLE); //DMA发送数据要先关闭,设置发送数据长度 开启DMA
DMA1_Channel4->CNDTR = size; //设置发送长度
GPIO_SetBits(GPIOB,GPIO_Pin_5);
DMA_Cmd(DMA1_Channel4, ENABLE); //启动DMA发送
return size;
}
/**
* @brief USART1发送数据1个字节
* @param dat,发送数据
* @retval 无
*/
void USART1_SendChar(u8 t)
{
USART_SendData(USART1,t);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
while((USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET));//等待串口发送完毕
}
/**
* @brief USART1发送字符串
* @param dat,发送数据
* @retval 无
*/
void USART1_SendString(void* buffer, uint16_t size)
{
uint8_t i=0,*buf;
buf=buffer;
GPIO_SetBits(GPIOB,GPIO_Pin_5);
while(size--)
{
USART1_SendChar(buf[i++]);
}
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
/**
* @brief USART1加密发送字符串
* @param dat,发送数据
* @retval 无
*/
void USART1_Encryption_SendString(void* buffer, uint16_t size)
{
uint8_t i=0,*buf;
//encryption(buffer,size);
buf=buffer;
GPIO_SetBits(GPIOB,GPIO_Pin_5);
while(size--)
{
USART1_SendChar(buf[i++]);
}
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
bsp_tim3.h
#ifndef __BSP_TIM3_H
#define __BSP_TIM3_H
#include "stm32f10x.h"
void TIM3_Int_Init(u16 arr,u16 psc);
#endif // __BSP_TIM3_H
bsp_tim3.c
#include "bsp_tim3.h"
extern uint16_t time;
//void TIM3_Int_Init(u16 arr,u16 psc)
//{
// TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//
// TIM_TimeBaseStructure.TIM_Period = arr;
// TIM_TimeBaseStructure.TIM_Prescaler =psc;
// TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
// TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
//
// TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
// NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// TIM_Cmd(TIM3, ENABLE);
//}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
TIM_ClearFlag(TIM3,TIM_IT_Update );
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
static u16 mS_Cnt_0=0;
static u16 mS_Cnt_1=0;
static u16 mS_Cnt_2=0;
static u16 mS_Cnt_3=0;
static u16 mS_Cnt_4=0;
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
// if(TIM2->SR&0X0001)//寄存器操作
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中断标志 ,库函数操作
//---------------------------------------[2]
time++;
//---------------------------------------[5]
}
}
// 延迟分钟函数
uint8_t delayed(uint8_t minute)
{
// 1分钟的
if(time == 6000 * minute)
{
time = 0;
return 0;
}
}
//void TIM3_IRQHandler(void) //TIM3中断
//{
// static uint16_t Sys_Cnt[5]={0};
// if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
// {
// time++;
// TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中断标志 ,库函数操作 TIM_IT_Update
// }
//}
//void BASIC_TIM_IRQHandler(void)
//{
// if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET )
// {
// time++;
// TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);
// }
//}
main.c
/**********************
芯片:STM32F103C8T6
实现功能:
引脚:PC13
***********************/
#include "stm32f10x.h"
#include "bsp_DMAusart1.h"
#include "bsp_tim3.h"
uint16_t time=0;
uint8_t time10 = 0;
int main()
{
USART1_Init(115200, OneUART.Tx_buf, OneUART.Rx_buf, USART1_REC_LEN);
USART1_DMASendString("time end!",sizeof("time end!"));
//每次进入中断服务程序间隔时间为((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒
//TIM3_Int_Init(9999, 71); // 1ms
//TIM3_Int_Init(59999, 71); // 60ms
//TIM3_Int_Init(59999, 7199); // 6s
//TIM3_Int_Init(59999, 35999); // 30s
while(1)
{
if(OneUART.Rx_end_flag)
{
if(OneUART.Rx_buf[0]== 0x01)
{
OneUART.Rx_buf[0] = 0x00;
TIM3_Int_Init(59999, 35999); // 30s
}
if(OneUART.Rx_buf[0]== 0x02)
{
OneUART.Rx_buf[0] = 0x00;
TIM_Cmd(TIM3, DISABLE);
}
}
// 1分钟
if(time == 2)
{
time = 0;
// USART1_DMASendString("time end!",sizeof("time end!"));
USART1_DMASendString("1分钟!",sizeof("1分钟!"));
time10++;
}
// 10分钟
if(time10 == 10)
{
time10 = 0;
USART1_DMASendString("10分钟!", sizeof("10分钟!"));
}
}
}
STM32_Project.zip