历史上的今天
返回首页

历史上的今天

今天是:2024年09月05日(星期四)

正在发生

2019年09月05日 | stm32输入捕获,捕获高电平

2019-09-05 来源:eefocus

输入捕获就是用定时器检测引脚上的电平时间,可以检测高电平时间和低电平时间,然后可以算引脚上信号的频率和占空比。


基本思路就是利用定时器的输入捕获功能。


定时器捕获到高电平或低电平就会进入捕获中断


例如:


我们要捕获高电平时间


0 设置定时器计数频率和装载值,一般设置1MHz,65535


1 设置定时器捕获为高电平捕获


2 进入捕获中断后,获取CNT计数值或CCRx值,定时器捕获到电平后会把CNT的值保存到CCRx。


   设置成低电平捕获。


3 再次进入捕获中断,获取CNT计数值-上次的CNT值=总高电平时间。


   设置成高电平捕获。


4 重复2-3即可完成下一次捕获。当然还要考虑溢出的情况,代码里有处理。


下面我写的一个实例:


1 定时器1 PA8产生PWM信号,可改变占空比,检测高电平时间


2 捕获定时器是定时器2,初始化如上例。


3 仿真改变PA8占空比,查看捕获出的高电平时间。


实测:


duty=1000就是高电平维持1000us,


捕获时间也是对应的1000us,一点误差都没有。


代码如下:


//高电平标志

u8  gao_flag=0;

//高电平时间

u32 gao_timer=0;

//捕获成功标志

u8  buhuo_flag=0;

//溢出次数

u8  yichu_c=0;

 

//定时器 5 中断服务程序

extern "C" void TIM2_IRQHandler(void)

{

  if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获

   {

 

 

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //这个是溢出中断

{

//如果已经得到高电平了,CNT溢出了

if(gao_flag==1)

{

 

yichu_c++;  //溢出加1

 

}

 

}

 

if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获 1 发生捕获事件

{

  if(0==gao_flag&&buhuo_flag==0) //说明之前没有捕获到高电平

{

gao_timer=TIM2->CCR1;  //获取高电平时间

 

yichu_c=0;       //溢出清零

gao_flag=1; //高电平标志

TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //改成下降沿捕获

}

//再一次进入捕获中断说明是捕获到下降沿了

else

{

if(buhuo_flag==0)   //判断是否捕获成功了,如果捕获成功了就不在捕获了

{

gao_timer=TIM2->CCR1-gao_timer;  //获取捕获到的高电平时间

gao_timer+=yichu_c*65536;       //加上溢出时间

 

TIM2->CNT=0; //计数清零

gao_flag=0;                   //高电平标志清零

buhuo_flag=1;             //标志捕获成功了

TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //改成上沿捕获

}

}

 

}

}

TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位

}

 

void TIM1_PWM_Init(u16 arr,u16 psc)

{

GPIO_InitTypeDef     GPIO_InitStrue;

    TIM_OCInitTypeDef     TIM_OCInitStrue;

    TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;

    

    

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);        //使能TIM3和相关GPIO时钟

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 使能GPIOB时钟(LED在BP5引脚),使能AFIO时钟(定时器3通道2需要重映射到BP5引脚)

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

    

    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_8;     // TIM_CH2

    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;    // 复用推挽

    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;    //设置最大输出速度

    GPIO_Init(GPIOA,&GPIO_InitStrue);                //GPIO端口初始化设置

    

//TIM1->CCMR1&=0xF7F7; //关闭事件更新值

//TIM1->CCMR1|=0x808; //开启事件更新值

 

    TIM_TimeBaseInitStrue.TIM_Period=50000;    //设置自动重装载值

    TIM_TimeBaseInitStrue.TIM_Prescaler=71;        //预分频系数

    TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;    //计数器向上溢出

    TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;        //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1

    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrue);        //TIM3初始化设置(设置PWM的周期)

    

    TIM_OCInitStrue.TIM_OCMode=TIM_OCMode_PWM2;        // PWM模式2:CNT>CCR时输出有效

    TIM_OCInitStrue.TIM_OCPolarity=TIM_OCPolarity_Low;// 设置极性-有效为高电平

    TIM_OCInitStrue.TIM_OutputState=TIM_OutputState_Enable;// 输出使能

TIM_OCInitStrue.TIM_Pulse=100;

    TIM_OC1Init(TIM1,&TIM_OCInitStrue);        //TIM3的通道2PWM 模式设置

 

    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);        //使能预装载寄存器

    

    TIM_Cmd(TIM1,ENABLE);        //使能TIM3

TIM_CtrlPWMOutputs(TIM1, ENABLE);  

TIM1->CCMR1&=0xF7F7; //关闭事件更新值

}

 

void capture_init(u16 arr,u16 psc)

{

TIM_OCInitTypeDef TIM2_OCInitStructure;

TIM_ICInitTypeDef TIM2_ICInitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;

 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能 TIM2 时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉

 

//初始化定时器 2 TIM2

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(TIM2, &TIM_TimeBaseStructure); //初始化 TIMx 的时间基数单位

 

//初始化 TIM2 输入捕获参数

 

TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到 TI1 上

TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获

TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上

TIM2_ICInitStructure.TIM_ICPrescaler = TIM_CKD_DIV1; //配置输入分频,不分频

TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波

TIM_ICInit(TIM2, &TIM2_ICInitStructure);

 

 

//中断分组初始化

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2 中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 2 级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能

NVIC_Init(&NVIC_InitStructure); //初始化外设 NVIC 寄存器

TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);

 

TIM_Cmd(TIM2,ENABLE ); //使能定时器3

}

 

u16 duty=1000;

 

int main(void)

{

 

   

   serial_init(115200); //串口初始化为 9600

   

   TIM1_PWM_Init(1000,71); //

PAout(1)=1;

   capture_init(0XFFFF,72-1); //以 1Mhz 的频率计数

printf("initrn");

  while(1)

   {

 

//测试位运算和逻辑运算的速度

 

PAout(1)=1;

  

 

 

TIM1->CCR1=duty;

 

    delay_ms(10);

 

if(buhuo_flag==1)

{

printf("HIGH1:%d us rn",gao_timer); //打印总的高点平时间

buhuo_flag=0;  //重新捕获

}

PAout(1)=0;

  delay_ms(10);

 

   }

 

}



推荐阅读

史海拾趣

CYANLITE公司的发展小趣事

CYANLITE公司非常重视产品品质的管理和控制。他们建立了严格的质量检测体系,确保每一件产品都符合高标准的质量要求。此外,公司还注重客户反馈的收集和分析,不断改进产品和服务以满足客户的需求。这种对品质的执着追求使得CYANLITE公司赢得了客户的信任和忠诚。许多客户都表示愿意长期与CYANLITE公司合作,并推荐他们的产品给其他人。

Eurofarad公司的发展小趣事

在追求经济效益的同时,Eurofarad也积极履行社会责任,注重环保和可持续发展。公司采用环保材料和绿色生产工艺,降低生产过程中的能耗和排放。同时,Eurofarad还积极参与环保公益活动,推动电子行业的绿色发展。这些举措不仅提升了公司的社会形象,也为公司的长远发展奠定了基础。

德索五金(dosinconn)公司的发展小趣事
固驰(GUERTE)公司的发展小趣事

在快速发展的同时,固驰电子始终不忘履行社会责任。公司积极参与公益事业,关注环境保护和可持续发展。通过采用环保材料和节能技术,固驰电子努力降低生产过程中的能耗和排放,为构建绿色、低碳的生态环境贡献力量。此外,公司还注重员工培训和职业发展,为员工提供良好的工作环境和晋升机会,实现了企业与员工的共同成长。

HM International公司的发展小趣事

随着产品质量的不断提升和技术的持续创新,固驰电子开始积极拓展国内外市场。公司产品不仅畅销国内市场,为美的、格力、艾美特等知名企业配套,还大量出口至韩国、俄罗斯、美国、加拿大、德国等国家和地区。这一过程中,固驰电子凭借其优良的品质、满意的价格和完善的服务赢得了国内外客户的一致好评,品牌影响力显著提升。

Deutron Electronics Corp公司的发展小趣事

为了进一步提升竞争力,Deutron Electronics Corp积极寻求国际合作与并购机会。公司与多家国际知名电子企业建立了战略合作关系,共同研发新产品和技术。同时,公司还成功收购了几家具有核心技术的电子企业,增强了自身的研发和生产能力。这些合作与并购为Deutron Electronics Corp带来了更多的发展机遇和市场空间。

问答坊 | AI 解惑

单片机小制作

适合于初学者 [ 本帖最后由 zhaobqing163 于 2008-11-29 18:17 编辑 ]…

查看全部问答>

求西门子plc的工业网络实验室的发展史

急求西门子plc的工业网络实验室的发展史。plc  的S7 300或者400的组成结构应用…

查看全部问答>

Keil 入门实例教程

Keil 入门实例教程…

查看全部问答>

STM8普及,无需ST-Link,新买的器件可以无限次数串口下载程序

STM8的单片机,只要内部是空的,就算Bootloader disable,也会上电运行Bootloader,可以从串口下载程序。新的器件虽然Bootloader disable,但是也可以用串口下载至少一次程序。 如果是一般的程序下载后,Bootloader是disable,那么不借助ST- ...…

查看全部问答>

请教大家一个很弱的问题,LM124是几伏电压供电?

在资料上看到LM124的供电电压范围是3~30V,可是我在调试板子的时候发现当变动LM124的供电电压时,输出端电压会随着改变,请问LM124的供电电压到底应该是多少?…

查看全部问答>

PLL输出差分时钟信号

请问如何用PLL#_CLKOUTp和 PLL#_CLKOUTn输出差分时钟,我先前都是用一般IO通过PLL中调整相位至180输出的,不知道用这两个脚如何实现。期待>>>>>>>>>>>>>>…

查看全部问答>

150°环境温度下使用的升压芯片

    我要做一个将锂电池3.7V升压到5V给单片机供电的电路,请求高手指教~~不胜感激~~…

查看全部问答>

LM3S8962模拟SPI驱动VS1003学习心得

LM3S8962模拟SPI驱动VS1003学习心得     倒腾了很久,参考了高手给我的一个程序,终于用VS1003听到声音了。这里也和大家分享一下我的学习心得~~人人助我,我助人人~~         这段时间仔细的研究了一下I ...…

查看全部问答>

MIPI 接口编程

大家看看用STM32给MIPI模块通信,大家帮忙看看方案可行不。附件是MIPI 的数据格式, 包括读和写。我原来想用PIC18F来做,利用SPI 可以做到高速写, 数据率10MHz, 但问题是 MIPI读写公用SDATA线,而PIC18F SPI 入和出是分开的 MOSI, MISO. 不知道有 ...…

查看全部问答>