找回密码
 立即注册
楼主: Crystalline

PWM输入捕获请教

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:173
  • 最近打卡:2025-05-01 12:26:51
已绑定手机

17

主题

81

回帖

382

积分

中级会员

积分
382
发表于 2025-1-11 10:31:27 | 显示全部楼层
梁*** 发表于 2025-1-10 16:56
应该用unsigned int型,已通知修改手册。

unsigned int 应该也不行吧,前一次捕获值和后一次捕获值相减可能为负数,unsigned int会溢出

点评

不会的,使用u16的类型,16位无符号相减,只计算差值,没有负数的。  详情 回复 发表于 2025-1-11 11:41
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-04-30 22:59:03

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2025-1-11 11:41:24 | 显示全部楼层
Crysta*** 发表于 2025-1-11 10:31
unsigned int 应该也不行吧,前一次捕获值和后一次捕获值相减可能为负数,unsigned int会溢出 ...

不会的,使用u16的类型,16位无符号相减,只计算差值,没有负数的。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:173
  • 最近打卡:2025-05-01 12:26:51
已绑定手机

17

主题

81

回帖

382

积分

中级会员

积分
382
发表于 2025-1-11 19:56:05 | 显示全部楼层
梁*** 发表于 2025-1-11 11:41
不会的,使用u16的类型,16位无符号相减,只计算差值,没有负数的。

哦哦对的对的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:173
  • 最近打卡:2025-05-01 12:26:51
已绑定手机

17

主题

81

回帖

382

积分

中级会员

积分
382
发表于 2025-1-11 19:59:41 | 显示全部楼层
  1. #include <STC8H.H>
  2. #include <Seg.h>
  3. #include <String.h>
  4. uchar Seg_Buf[] = {10,10,10};
  5. uchar pos = 0;
  6. uint Seg_Slow_Down = 0;
  7. uint Time_1000ms = 0;
  8. uint Freq = 0;
  9. uchar Time1ms = 0;
  10. uchar count_100ms;
  11. bit is_in_interrupt;
  12. uchar led_light = 2;
  13. float sum;
  14. uchar i;
  15. #define FILTER_SIZE 30
  16. #define SYS_CLK 1000.0
  17. int filter_buffer[FILTER_SIZE];  // 存储最新的30个频率值
  18. int filter_index = 0;            // 用于指示当前存储位置
  19. float filtered_freq = 0;           // 存储滤波后的频率值
  20. typedef struct {
  21.         long cap;
  22.         long cap_new;
  23.         long cap_old;
  24. }Freq_Type;
  25. Freq_Type Freq1;
  26. Freq_Type Freq2;
  27. Freq_Type Freq3;
  28. long Old;
  29. void Timer1_Isr(void) interrupt 3
  30. {
  31.         if(++Seg_Slow_Down == 5000) {Seg_Slow_Down = 0; }
  32.         if(++Time1ms == 10){
  33.                 Time1ms = 0;
  34.                 if(++pos ==3) pos = 0;
  35.         }
  36.         if(Time1ms <= led_light)  //亮
  37.         {
  38.                 Seg_Disp(pos,Seg_Buf[pos]);
  39.         }
  40.         else
  41.                 Seg_Disp(pos,10);  //灭
  42. }
  43. void Timer1_Init(void)                //100微秒@12.000MHz
  44. {
  45.         AUXR &= 0xBF;                        //定时器时钟12T模式
  46.         TMOD &= 0x0F;                        //设置定时器模式
  47.         TL1 = 0x9C;                                //设置定时初始值
  48.         TH1 = 0xFF;                                //设置定时初始值
  49.         TF1 = 0;                                //清除TF1标志
  50.         TR1 = 1;                                //定时器1开始计时
  51.         ET1 = 1;                                //使能定时器1中断
  52. }
  53. void System_Init()
  54. {
  55.         P_SW2 |= 0x80; //扩展外部XFR
  56.         PWMB_PS = 0x54; //01 01 01 00 选用P54\P33\P34作为输入捕获引脚
  57.         PWMB_PSCRH = 0x2E; //预分频寄存器  1000分频
  58.         PWMB_PSCRL = 0xDF;
  59.         /*必须先关闭CCER才能设置CC1*/
  60.         PWMB_CCER1 = 0x00;PWMB_CCER2 = 0x00 ;
  61.         PWMB_CCMR2 = 0x01;PWMB_CCMR3 = 0x01;        PWMB_CCMR4 = 0x01;                       //通道6、7、8设为输入
  62.         //PWMB_CCMR2 |= 0xC0; PWMB_CCMR3 |= 0xC0; PWMB_CCMR4 |= 0xC0;  //8个事件触发一次
  63.         PWMB_CCER1 = 0x10; PWMB_CCER2 = 0x11; //使能通道6、7、8
  64.         PWMB_IER = 0x1C;
  65.         PWMB_CR1 |= 0x01; //使能计数器
  66.         IP |= 0x0f; //拉低定时器1的优先级
  67.         P1M0 = 0xff; P1M1 = 0x00;
  68.   P5M0 = 0x00; P5M1 = 0x10;
  69.   P3M0 = 0xe0; P3M1 = 0x18;
  70.        
  71.         Timer1_Init();
  72.         EA = 1;
  73. }
  74. void Seg_Proc()
  75. {
  76.         sum = 0;
  77.         i = 0;
  78.         if(Seg_Slow_Down) return;
  79.         Seg_Slow_Down = 1;
  80.        
  81.         for(i = 0;i<FILTER_SIZE;i++)
  82.                 sum += filter_buffer[i];
  83.        
  84.         if(Freq1.cap_old != Freq1.cap_new){
  85.                 filtered_freq = sum / FILTER_SIZE;
  86.                 filtered_freq = SYS_CLK / filtered_freq;
  87.         }
  88.         else
  89.                 filtered_freq = 0;
  90.         //Freq = Freq1.cap + Freq2.cap + Freq3.cap;
  91. //        if(Freq <= 999){
  92. //                Seg_Buf[0] = (Freq/100)?Freq/100:10;
  93. //                Seg_Buf[1] = (Freq/10)?Freq/10%10:10;
  94. //                Seg_Buf[2] = Freq%10;       
  95. //        }
  96. //        else
  97. //                Seg_Buf[0] = Seg_Buf[1] = Seg_Buf[2] = 9;
  98.        
  99.        
  100.   Seg_Buf[0] = ((uint)(filtered_freq/100))?(uint)(filtered_freq/100):10;
  101.         Seg_Buf[1] = ((uint)(filtered_freq/10))?(uint)(filtered_freq/10)%10:10;
  102.         Seg_Buf[2] = (uint)filtered_freq%10;       
  103.        
  104. }
  105. void main()
  106. {
  107.         System_Init();
  108.         while(1)
  109.         {
  110.                 Seg_Proc();
  111.         }
  112. }
  113. void PWMB_ISR() interrupt 27
  114. {
  115.         if(PWMB_SR1 & 0x04) //是CC6的中断
  116.         {
  117.                 Freq1.cap_old = Freq1.cap_new;
  118.                 Freq1.cap_new = PWMB_CCR6;
  119.                 Freq1.cap = Freq1.cap_new - Freq1.cap_old;       
  120.                
  121.                 filter_buffer[filter_index] = (Freq1.cap >= 0) ? Freq1.cap : -Freq1.cap;
  122.                 filter_index = (filter_index + 1) % FILTER_SIZE;
  123.                
  124.                 PWMB_SR1 &= ~0x04;
  125.                
  126.         }
  127. //        if(PWMB_SR1 & 0x08) //是CC7的中断
  128. //        {
  129. //                Freq2.cap_old = Freq2.cap_new;
  130. //                Freq2.cap_new = PWMB_CCR7;
  131. //                Freq2.cap = Freq2.cap_new - Freq2.cap_old;
  132. //                PWMB_SR1 &= ~0x08;               
  133. //        }
  134. //        if(PWMB_SR1 & 0x10) //是CC8的中断
  135. //        {
  136. //                Freq3.cap_old = Freq3.cap_new;
  137. //                Freq3.cap_new = PWMB_CCR8;
  138. //                Freq3.cap = Freq3.cap_new - Freq3.cap_old;
  139. //                PWMB_SR1 &= ~0x10;               
  140. //        }
  141. }
复制代码
我现在有个问题就是他没有频率输入以后,还会保持之前的频率值,这个问题怎么解决

点评

采样窗口时间(超时),即超过一定时间没有脉冲就要归0.  详情 回复 发表于 2025-1-11 21:18
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-04-30 22:59:03

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2025-1-11 21:18:36 | 显示全部楼层
Crysta*** 发表于 2025-1-11 19:59
我现在有个问题就是他没有频率输入以后,还会保持之前的频率值,这个问题怎么解决
...

采样窗口时间(超时),即超过一定时间没有脉冲就要归0.
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-03-30 12:16:48
已绑定手机

1

主题

6

回帖

39

积分

新手上路

积分
39
发表于 2025-3-30 12:16:48 | 显示全部楼层
你这部分计算的代码最好别放在中断里运行,会占用太多资源
截图202503301214477124.jpg
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:35 , Processed in 0.151550 second(s), 91 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表