找回密码
 立即注册
查看: 9|回复: 1

利用PWM实现串口硬件超时中断

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:703
  • 最近打卡:2026-04-14 22:58:33
已绑定手机
已实名认证

131

主题

3406

回帖

8884

积分

版主

积分
8884
发表于 昨天 22:58 | 显示全部楼层 |阅读模式
STC32G12K128/STC32G8K64系列芯片的串口超时中断功能,因为需要进入串口中断额外处理,所以在高波特率接受场景,易造成中断过多
(Ai8051U、STC32G144K246新版的硬件超时中断修复了这个问题)

以及,带有串口DMA接受,但是无硬件超时中断的AI8H8K64U、Ai8H4K64TLCD、Ai8H1K08T也可以参考此进行功能增加

从而可以方便的完成高速串口接受不定长数据,且包与包之间间隔较短的情况。


说明:此功能需要占用完整的一组PWM,PWM不能做其他用处了,一组PWM可以用于一个串口接受的监控,PWMA和PWMB两组就可以分别用作两个串口的接受超时中断

超时中断时钟数可设置,且拥有硬件中断(PWM中断)


以下程序以STC32G12K128为演示平台,设置主频为24Mhz,需要外部短接PWM1P(P20)和RXD(P30)
串口通讯频率选择为500Kbps,通过串口助手发送后,会在结束后返回当前发送了多长的数据(通过DMA接受完成字节读取)
这里可以通过调整程序设置,实现PWMA组通过PWM1P或PWM2P监控,PWMB组通过PWM5或PWM6监控
以下为演示效果:
发送了三个字符串,右边的HEX蓝色为单片机返回的字符长度
截图202604142247042152.jpg
程序的思路为:
使用SMCR从模式的触发模式(定时器CEN启动受控,关闭不受控),设置下降沿有效(串口的起始位),等待有效边沿来启动PWMA定时器
第一个下降沿后,PWM计数器开始向上计数,超过CCR3设置的值后,通过通道3比较中断,来切换为复位模式(有效边沿时复位CNTR,同时关闭通道3中断(较小值),设置有效边沿为上升沿有效(串口的结束位)
复位模式下只要有数据就会不断清空CNTR,如果长时间没发数据,CNTR持续增长,超过CCR4设置的值后,通道4(较大值)比较中断触发,清空CNTR,然后切换为触发模式,关闭PWM定时器,并且打开通道3比较,等待第二次发送。这个时候就可以作为超时中断引出了
给客户只需要引出通道4比较中断即可。通道12需要留作输入(方便切换PWM1P或者PWM2P的所有IO口),不可更改。



以下为完整程序(仅PWM中断部分,主循环无需多余代码)
  1. ////////////////////////////////////////
  2. // PWMA中断服务程序
  3. // 入口参数: 无
  4. // 函数返回: 无
  5. ////////////////////////////////////////
  6. void PWMA_ISR(void) interrupt PWMA_VECTOR
  7. {
  8.     //<<AICUBE_USER_PWM0_ISR_CODE1_BEGIN>>
  9.     // 在此添加中断函数用户代码  
  10.                 sr1 = PWMA_SR1;
  11.                 sr1 &= PWMA_IER;
  12.                 //启动触发点
  13.     if (sr1&0x08)            //判断PWM捕获/比较中断
  14.     {
  15.                                 //PWMA_CNTRH = 0x00;//可选,更稳定一些
  16.                                 //PWMA_CNTRL = 0x00;
  17.                                 PWMA_SMCR = 0x54;//(PWM1P输入)+(复位模式)
  18.                                 PWMA_IER = 0x10;//关闭启动触发点1
  19.                                 PWMA_CCER1 = 0x11;//上升沿有效
  20.     }
  21.                 //超时触发点
  22.                 if (sr1&0x10)            //判断PWM捕获/比较中断
  23.     {      
  24.                                 PWMA_CR1 = 0x00;
  25.                                 PWMA_CNTRH = 0x00;
  26.                                 PWMA_CNTRL = 0x00;
  27.                                 PWMA_SMCR = 0x56;//(PWM1P输入)+(触发模式)
  28.                                 PWMA_IER = 0x08;//CC3,CC4中断
  29.                                 PWMA_CCER1 = 0x33;//下降沿有效
  30.                                 SBUF = DMA_UR1R_DONE;//测试数据,接受了多少个长度的数据
  31.                                 DMA_UR1R_CR = 0x00;//关闭DMA
  32.         DMA_UR1R_CR = 0xA1;//重新开始接受
  33.     }
  34.                 PWMA_SR1 = 0x00;//清除PWM捕获/比较中断标志
  35.     //<<AICUBE_USER_PWM0_ISR_CODE1_END>>
  36. }
  37. //<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
  38. // 在此添加用户函数实现代码  
  39. void PWM_OVER_Init(void)
  40. {
  41.                 PWMA_ENO = 0x00;//关闭所有输出通道
  42.                 PWMA_CR1 = 0x00;
  43.                 PWMA_CR2 = 0x00;
  44.                 PWMA_SMCR = 0x56;//(PWM1P输入)+(触发模式)
  45.                 //PWMA_SMCR = 0x54;//(PWM1P输入)+(复位模式)
  46.                 PWMA_IER = 0x08;//CC3中断
  47.                 PWMA_CCER1 = 0x00;
  48.                 PWMA_CCER2 = 0x00;
  49.                 PWMA_CCMR1 = 0x01;//TI1FP1
  50.                 PWMA_CCMR2 = 0x01;//TI2FP2
  51.                 PWMA_CCMR3 = 0x60;//输出,关闭预装载
  52.                 PWMA_CCMR4 = 0x60;//输出,关闭预装载
  53.                 PWMA_CCER1 = 0x33;//下降沿有效
  54.                 //PWMA_CCER1 = 0x11;//上升沿有效
  55.                 PWMA_CCER2 = 0x11;//CC3,4使能
  56.                 PWMA_CNTRH = 0x00;
  57.                 PWMA_CNTRL = 0x00;
  58.                 PWMA_PSCRH = 0x00;
  59.                 PWMA_PSCRL = 0x00;
  60.                 PWMA_ARRH = 0xff;
  61.                 PWMA_ARRL = 0xff;
  62.                 PWMA_RCR = 0x00;
  63.                 PWMA_CCR3H = *(unsigned char *)&cap1;
  64.                 PWMA_CCR3L = *((unsigned char *)&cap1+1);
  65.                 PWMA_CCR4H = *(unsigned char *)&cap2;
  66.                 PWMA_CCR4L = *((unsigned char *)&cap2+1);
  67.                 PWMA_BKR = 0x80;
  68.                 PWMA_EGR = 0x01;
  69. }
  70. //<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
复制代码
以下为使用STC32G12K128的测试程序,在屠龙刀3.2板上测试通过
uart1_over.zip (485.57 KB, 下载次数: 0)


这个程序目前设置的是PWM1P输入,如果想要用PWM1P的其他通道作为输入,可通过PWMA_PS切换到其他通道
如果恰好RXD跟PWM口在同一个端口上,则可以不用外部飞线,直接就可以使用这个硬件超时功能
例如STC32G12K128中,串口2的P1.0和P1.1,串口3的P0.0和P0.1就可以直接使用
截图202604142255303712.jpg 截图202604142255343749.jpg


如果想要切换为PWM2P输入,只需要更改高4位为6即可,
使用PWMB组,可以直接更换PWMA关键词为PWMB,然后CCR1,2,3,4对应CCR5,6,7,8即可实现替换

PWMA_SMCR = 0x66;//(PWM2P输入)+(触发模式)
PWMA_SMCR = 0x64;//(PWM2P输入)+(复位模式)

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:219
  • 最近打卡:2026-04-15 00:01:34
已绑定手机

17

主题

331

回帖

1622

积分

金牌会员

DIY玩家

积分
1622
发表于 6 小时前 | 显示全部楼层
引脚功能可以切换
方便灵活设计
真正的学徒往往怀着大师的心
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-4-15 06:05 , Processed in 0.113129 second(s), 51 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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