打印
[PIC®/AVR®/dsPIC®产品]

PIC12F675定时器无法实现100KHz输出???

[复制链接]
1499|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
streetkid|  楼主 | 2022-1-12 22:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
第一次用PIC的片子,想用PIC12f675实现100KHz的PWM输出,看了下手册算了下应该是可以做1us定时的。但搞了半天最高只能输出15KHz。大家帮忙看看问题出在了哪里?
#include<pic12f675.h>

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = ON        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

#define nop() asm("NOP")

#define u8 unsigned char
#define u16 unsigned int

#define PWM_A GPIO2
#define LED GPIO1

u8 n = 0;

void init(void)
{
    CMCON = 0x07;
    ANSEL = 0x00;  
    WPU |= 0x20;
    TRISIO = 0x38;
   
    TMR0 = 0xFF;   
    //OPTION_REG
    T0CS = 0;
    PSA = 1;
   
    //INTCON
    T0IF = 0;
    T0IE = 1;
    GIE = 1;
}

void __interrupt(low_priority) tmer0(void)
{
     if(T0IF==1)
         {
         TMR0 = 0xFF;
         T0IF = 0;
         n++;
         if(n==1)
            PWM_A = 1;
         else
         {
             PWM_A = 0;
             n = 0;
         }
     }
}
void main(void)
{
    init();
    while(1);
}

使用特权

评论回复
沙发
streetkid|  楼主 | 2022-1-13 17:50 | 只看该作者
自己顶一下吧

使用特权

评论回复
板凳
delong_z| | 2022-1-13 18:39 | 只看该作者
楼主,用新的型号,MCC生成代码几分钟就搞定了。加我VX 13251345724

使用特权

评论回复
地板
lyjian| | 2022-1-13 22:21 | 只看该作者
软件做100KHz PWM?
你是开玩笑吧

使用特权

评论回复
5
streetkid|  楼主 | 2022-1-14 09:23 | 只看该作者
lyjian 发表于 2022-1-13 22:21
软件做100KHz PWM?
你是开玩笑吧

为啥不行呢?看手册TIMR0不分频正好是1us啊,内部时钟4MHz

使用特权

评论回复
6
粤原点科技| | 2022-1-14 09:35 | 只看该作者
streetkid 发表于 2022-1-14 09:23
为啥不行呢?看手册TIMR0不分频正好是1us啊,内部时钟4MHz

PIC12F675单指令周期=(1/4000000)*4=1us,软件模拟PWM。除非其他事情都不做,CPU资源被这个软件模拟PWM一直占用,只输出PWM,并且PWM的位数极低,这样做就没意义了。
PS:跑指令也是需要时间的

使用特权

评论回复
7
lcczg| | 2022-1-14 11:09 | 只看该作者
楼上正解,楼主可以选带PWM外设的器件。

使用特权

评论回复
8
streetkid|  楼主 | 2022-1-14 12:10 | 只看该作者
粤原点科技 发表于 2022-1-14 09:35
PIC12F675单指令周期=(1/4000000)*4=1us,软件模拟PWM。除非其他事情都不做,CPU资源被这个软件模拟PWM一 ...

感谢,不过我也做啥操作啊,就消耗了60多条指令了?

使用特权

评论回复
9
lyjian| | 2022-1-14 12:48 | 只看该作者
streetkid 发表于 2022-1-14 09:23
为啥不行呢?看手册TIMR0不分频正好是1us啊,内部时钟4MHz

1uS的指令周期,你要做1uS的定时中断?中断处理不要花时间吗?
100KHz=10uS,就算是做1bit PWM,也要5uS内处理一次,这小CPU忙得过来吗?

使用特权

评论回复
10
streetkid|  楼主 | 2022-1-14 15:58 | 只看该作者
lyjian 发表于 2022-1-14 12:48
1uS的指令周期,你要做1uS的定时中断?中断处理不要花时间吗?
100KHz=10uS,就算是做1bit PWM,也要5uS ...

确实是,即使做了也是问题多多。再次感谢。

使用特权

评论回复
11
粤原点科技| | 2022-1-15 11:54 | 只看该作者
streetkid 发表于 2022-1-14 12:10
感谢,不过我也做啥操作啊,就消耗了60多条指令了?

我也不清楚你的代码怎么写的,但用定时器来做,会更加耗时,而且判断标志位和清标志,再给TMR0赋初值,再执行模拟PWM的代码,这些都是消耗,写得不够精简的话60uS是会有的。又如果开了中断,进出中断的现场保护和现场恢复是8句代码就白白耗了8uS。极端的情况下,MCU只做PWM其他事不做,并且PWM位数是1bit,也就是直接翻转IO,下面的汇编代码,GP0完成2次翻转(1个方波)需要8us((1+1+2)*2)。这么极端的做法,频率也就125KHz。所以这么低主频+机器周期长(4T)的CPU,确实不适合做高速模拟PWM。可以换个其他型号带硬件PWM的。
MAIN_LOOP:
MOVLW   B'00000001'
XORWF   GPIO,F
GOTO      MAIN_LOOP


使用特权

评论回复
12
lyjian| | 2022-1-15 13:02 | 只看该作者
粤原点科技 发表于 2022-1-15 11:54
我也不清楚你的代码怎么写的,但用定时器来做,会更加耗时,而且判断标志位和清标志,再给TMR0赋初值,再 ...

不用重复MOVLW   B'00000001'

使用特权

评论回复
13
粤原点科技| | 2022-1-15 13:42 | 只看该作者
lyjian 发表于 2022-1-15 13:02
不用重复MOVLW   B'00000001'

是的,直接在主循环外边给W放0x01即可。

使用特权

评论回复
14
streetkid|  楼主 | 2022-1-17 09:26 | 只看该作者
粤原点科技 发表于 2022-1-15 11:54
我也不清楚你的代码怎么写的,但用定时器来做,会更加耗时,而且判断标志位和清标志,再给TMR0赋初值,再 ...

感谢,学习了

使用特权

评论回复
15
aoyi| | 2022-2-5 17:20 | 只看该作者
有些整值确实是输出不了

使用特权

评论回复
16
drer| | 2022-2-5 17:25 | 只看该作者
只要在一定的容差范围内就可以了

使用特权

评论回复
17
gwsan| | 2022-2-5 17:29 | 只看该作者
只要差不了太多就可以了

使用特权

评论回复
18
kxsi| | 2022-2-5 17:44 | 只看该作者
用c如何表述呢

使用特权

评论回复
19
nawu| | 2022-2-5 17:50 | 只看该作者
好像都是一样的算法

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

228

帖子

2

粉丝