初级会员

- 积分
- 94
- 金钱
- 94
- 注册时间
- 2016-3-24
- 在线时间
- 28 小时
|

楼主 |
发表于 2016-6-14 20:44:56
|
显示全部楼层
下面是本人根据原子哥之前的例程以及查数据手册等初略调试写出的一个程序,可以实现定时器输入捕获PWM信号同时通过DMA传输的实验程序。经过本人实验,是稳定可靠能用的,对遥控器的通道的读取能保证在0到100
之间的数据范围同时通道间不互相影响。因为只是实验的版本,所以写得有点乱,请勿喷,希望在这方面有所研究的朋友能共同交流,能够写出更好的程序出来。芯片用到的是STM32F051,主要程序配置如下:
/**************************************
* 函数名 : timer1_init
* 描述 : 定时器1的输入捕获加DMA初始化配置
* 输入参数 : 无
* 返回值 : 无
**************************************/
#define BUF_SIZE_TIM1 2 //定义数据的长度
uint32_t IC2Value_TIM1[BUF_SIZE_TIM1]={0,0}; //数据存放的数组
void timer1_init(uint16_t arr,uint16_t psc)
{
RCC->APB2ENR|=1<<11; //TIM1 时钟使能
RCC->AHBENR|=1<<17; //使能PORTA时钟
// PA引脚设置
GPIOA->MODER|=0x00820000; // PA.8、PA.11设置为AF模式;
GPIOA->OTYPER&=~0x0900; // 设置推挽输出;
GPIOA->OSPEEDR|=0x00c30000; // 设置IO口高速翻转;
GPIOA->PUPDR|=0x00820000; // 内部下拉;
GPIOA->AFR[1]|=0X02002; // AF2;
/*输入捕获需要用到中断的时候再打开*/
// // 配置NVIC,中断向量号TIM1_CC_IRQn= 14
// NVIC_SetPriority(TIM1_CC_IRQn, 0);
// NVIC->ISER[0] = (uint32_t)0x01 <<14; // 使能NVIC;
TIM1->ARR=arr; //设定计数器自动重装载值
TIM1->PSC=psc; //预分频器
TIM1->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上
TIM1->CCMR1|=0<<4; //IC1F=0000 配置输入滤波器 不滤波
TIM1->CCMR1|=0<<2; //IC1PS=00 配置输入分频,不分频
TIM1->CCMR2|=1<<8; //CC4S=01 选择输入端 IC4映射到TI4上
TIM1->CCMR2|=0<<12; //IC4F=0000 配置输入滤波器 不滤波
TIM1->CCMR2|=0<<10; //IC4PS=00 配置输入分频,不分频
TIM1->CCER|=0<<1; //CC1P=0 上升沿捕获
TIM1->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中
TIM1->CCER|=0<<13; //CC4P=0 上升沿捕获
TIM1->CCER|=1<<12; //CC4E=1 允许捕获计数器的值到捕获寄存器中
/*DMA配置*/
MYDMA_Config(DMA1_Channel2,(uint32_t)(&TIM1->CCR1),(uint32_t)(&IC2Value_TIM1[0]),1);
// MYDMA_Config(DMA1_Channel4,(uint32_t)(&TIM1->CCR4),(uint32_t)(&IC2Value_TIM1[1]),1);
/*定时器打开DMA传输的配置*/
TIM1->CR2|=0<<3; //当发生CCx事件时,送出CCx的DMA请求
TIM1->DIER|=1<<9; //允许CCR1 DMA捕获请求
//TIM1->DIER|=1<<12; //允许CCR4 DMA捕获请求
/*定时器打开中断传输的配置*/
// TIM1->DIER|=1<<1; //允许捕获1中断
// TIM1->DIER|=1<<4; //允许捕获4中断
// TIM1->DIER|=1<<0; //允许更新中断
TIM1->CR1|=0x01; //使能定时器1
}
///////////////DMA配置/////////////////
uint16_t DMA1_MEM_LEN;//保存DMA每次数据传送的长度
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,uint32_t cpar,uint32_t cmar,uint32_t cndtr)
{
uint32_t DR_Base; //做缓冲用,不知道为什么.非要不可
RCC->AHBENR|=1<<0;//开启DMA1时钟
DR_Base=cpar;
DMA_CHx->CPAR=DR_Base; //DMA1 外设地址
DMA_CHx->CMAR=(uint32_t)cmar; //DMA1,存储器地址
DMA1_MEM_LEN=cndtr; //保存DMA传输数据量
DMA_CHx->CNDTR=cndtr; //DMA1,传输数据量
DMA_CHx->CCR=0X00000000;//复位
DMA_CHx->CCR|=0<<4; //从外设读
DMA_CHx->CCR|=1<<5; //循环模式
DMA_CHx->CCR|=0<<6; //外设地址非增量模式
DMA_CHx->CCR|=1<<7; //存储器增量模式
DMA_CHx->CCR|=2<<8; //外设数据宽度为32位
DMA_CHx->CCR|=2<<10; //存储器数据宽度32位
DMA_CHx->CCR|=2<<12; //高等优先级
DMA_CHx->CCR|=0<<14; //非存储器到存储器模式
// /* 开启DMA1_Channel2、DMA1_Channel3通道中断控制,0级先占优先级,0级次占优先级*/
// // 配置NVIC,中断向量号DMA1_Ch2_3= 10
// NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0);
// NVIC->ISER[0] = (uint32_t)0x01 <<10; // 使能NVIC;
}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
}
/*TIM1数据采集回来后的处理程序*/
uint8_t TIM1_CAPTURECH_STA1=0; //输入捕获状态
uint8_t TIM1_CAPTURECH_STA4=0; //输入捕获状态
uint8_t duty_b_CH5=0; //遥控最终的读数
uint8_t duty_b_CH6=0; //遥控最终的读数
uint16_t TIM1_CH1ReadValue= 0; //TIM1->CCR1采集的数值
uint16_t TIM1_CH4ReadValue= 0; //TIM1->CCR4采集的数值
uint32_t temp_CH5=0;
uint32_t temp_CH6=0;
void TIM1CH1_CaptureHandle_Program(void)
{
if(TIM1_CAPTURECH_STA1&0X40) //捕获到一个下降沿
{
TIM1_CAPTURECH_STA1|=0X80; //标记成功捕获到一次高电平脉宽
TIM1_CH1ReadValue=IC2Value_TIM1[0]; //获取当前的捕获值.
temp_CH5=TIM1_CAPTURECH_STA1&0X3F;
temp_CH5+=TIM1_CH1ReadValue; //得到总的高电平时间
duty_b_CH5=(uint8_t)((temp_CH5-2000)*0.1);
if((0<duty_b_CH5)&&(duty_b_CH5<5)) //开关信号
{ duty_b_CH5=0xAA;}
if((44<duty_b_CH5)&&(duty_b_CH5<55)) //关闭信号
{ duty_b_CH5=0xBB;}
TIM1_CAPTURECH_STA1=0; //开启下一次捕获
TIM1->CCER&=~(1<<1); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM1_CAPTURECH_STA1=0; //清空
TIM1_CH1ReadValue=0; //
TIM1_CAPTURECH_STA1|=0X40; //标记捕获到了上升沿
TIM1->CNT=0; //计数器清空
TIM1->CCER|=1<<1; //CC1P=1 设置为下降沿捕获
}
}
/**************************************
* 函数名 : main
* 描述 : 主函数
* 输入参数 : 无
* 返回值 : 无
**************************************/
int main(void)
{
UserSystemClock48MInit(Internal_Clock_Source);
LED_Init();
SysTick_Init(); //开启延时
USART_Configuration(); /* USART1 config 115200 8-N-1 */
//LED灯控制程序
UserTIMER1617PWMInit(1000); //1000hz频率
//遥控通道
timer1_init(65535,48-1);// 定时器初始化配置 48/48=1M的计数频率,自动重装载值为65536
while (1)
{
MYDMA_Enable(DMA1_Channel2); //开始一次DMA传输
if(DMA1->ISR&(1<<5))//等待通道2传输完成
{
LED_ON_D4;
TIM1CH1_CaptureHandle_Program();
DMA1->IFCR|=1<<5;//清除通道2传输完成标志
}
}
}
|
|