找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1478|回复: 12
打印 上一主题 下一主题
收起左侧

利用pic16f676单片机定时器控制RA0端口发光二极管闪烁,请大佬帮我看看哪里问题

[复制链接]
跳转到指定楼层
楼主
ID:1107532 发表于 2024-1-2 11:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
利用pic16f676单片机定时器控制RA0端口发光二极管闪烁,开始一段时间不亮,然后一直亮,无法闪烁,改了很多次,不知道是不是中断设置问题。拜托大佬帮我看看!
# include <xc.h>
#pragma config FOSC = INTRCIO  
#pragma config WDTE = OFF   
#pragma config PWRTE = ON      
#pragma config MCLRE = OFF   
#pragma config BOREN = OFF      
#pragma config CP = OFF        
#pragma config CPD = OFF      

#define uchar unsigned char
#define uint unsigned int

uint intnum;

void init()  //定时器初始化设置
{   
    //T0CS=0;   //Timer0使用内部时钟             OPTION_REG - 选择寄存器
    //PSA=1;   //将预分频器给看门狗WDT           OPTION_REG -选择寄存器
    //PS0=1;
    //PS1=1;
    //PS2=0;
    //TMR0=0x00; //定时器
    //T0IF=1;  //Timer0 启动控制位使能(0关闭)(标志位)    INTCON - 中断控制寄存器
    //T0IE=1;  //Timer0中断开启(使能位)                   INTCON - 中断控制寄存器
    //WDTE=1;

    TMR1CS=0;   //Timer1使用内部时钟           Timer1 控制寄存器
    T1CKPS0=1;  //1:8倍预分频比                Timer1 控制寄存器      T1CKPS1:T1CKPS0:11=1:8倍预分频比
    T1CKPS1=1;  //1:8倍预分频比                Timer1 控制寄存器
    //TMR1H=(65536-(50000/3))/256; //初始化TMR1的高八位初始值
    //TMR1L=(65536-(50000/3))%256; //初始化TMR1的低八位初始值
    TMR1H=0x0B;  //高八位置初始值    00001011
    TMR1L=0xE9;  //低八位置初始值    11101001
    TMR1ON=1;  //Timer1 启动控制位使能(0关闭)       Timer1 控制寄存器
    TMR1IF=0;  //中断标志位清零                      外设中断标志寄存器 1
    TMR1IE=1;  //Timer1中断开启                      外设中断使能寄存器 1
    PEIE=1;  //外部中断开启                          INTCON - 中断控制寄存器
    GIE=1;  //全局中断开启                           INTCON - 中断控制寄存器
}


void main ()
{
    TRISA=0b00110100;  //RA2,RA4,RA5为输入,其他输出
    TRISC=0b00010011;  //RC0、RC1、RC4为输入,其他输出
    PORTA=0b00000000;  //RA口输出低电平
    PORTC=0b00000000;  //RC口输出低电平   
    init();
    while(1)
    {
       /* if (intnum ==20) //中断溢出计数达到20次  20*50ms=1秒亮一次
        {
            intnum = 0;  //溢出次数清零
            RA0 = !RA0;  //RA0端口取反为1,链接RA0端口的发光二极管形成电势差发亮
        }*/
    }
}

void interrupt ISR()
{
    if (TMR1IF == 1)
    {
        TMR1IF=0;  //中断标志溢出清0
        //TMR1H=(65536-(50000/3))/256; //初始化TMR1的高八位初始值
        //TMR1L=(65536-(50000/3))%256; //初始化TMR1的低八位初始值
        TMR1H=0x0B;  //高八位置初始值    00001011
        TMR1L=0xE9;  //低八位置初始值    11101001
        intnum++;

        if (intnum==173)
        {
            intnum = 0;
            RA0 = !RA0;
        }
    }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:607298 发表于 2024-1-2 14:57 | 只看该作者
刚开始要一步步来。
首先要配置RA0,确定输出高低电平可控。
大概看下程序,RA0模拟通道AN0,CIN+没有关闭,RA0应该无法高低电平输出。
然后再确认计时中断正常触发。

有硬件调试工具的话,你可以打断点,查看相关寄存器和变量,来解决问题。
没有话,建议你使用proteus软件模拟仿真运行程序。
回复

使用道具 举报

板凳
ID:1107532 发表于 2024-1-3 09:30 | 只看该作者
lightday 发表于 2024-1-2 14:57
刚开始要一步步来。
首先要配置RA0,确定输出高低电平可控。
大概看下程序,RA0模拟通道AN0,CIN+没有关 ...

大佬,我就是检测出好像没有循环中断,请问一下CIN+没有关闭是什么啊,我是刚刚入行的小白,有点不懂
回复

使用道具 举报

地板
ID:1107532 发表于 2024-1-3 09:32 | 只看该作者
lightday 发表于 2024-1-2 14:57
刚开始要一步步来。
首先要配置RA0,确定输出高低电平可控。
大概看下程序,RA0模拟通道AN0,CIN+没有关 ...

请问CIN+是要对RA0进行A/D模拟转换吗
回复

使用道具 举报

5#
ID:1093268 发表于 2024-1-4 10:39 | 只看该作者
ANSEL &= 0xFE;
CMCON = 0x07;
IO初始化时,加这2句就好了。
回复

使用道具 举报

6#
ID:1107532 发表于 2024-1-4 13:42 | 只看该作者
哦豁~ 发表于 2024-1-4 10:39
ANSEL &= 0xFE;
CMCON = 0x07;
IO初始化时,加这2句就好了。

大佬,我加上去后,还是无法实现
回复

使用道具 举报

7#
ID:1107532 发表于 2024-1-4 14:02 | 只看该作者
哦豁~ 发表于 2024-1-4 10:39
ANSEL &= 0xFE;
CMCON = 0x07;
IO初始化时,加这2句就好了。

可以实现了,非常感谢大佬,那个取反的语句一直没有执行,是因为CIN+没有关闭
回复

使用道具 举报

8#
ID:1107532 发表于 2024-1-4 14:38 | 只看该作者
哦豁~ 发表于 2024-1-4 10:39
ANSEL &= 0xFE;
CMCON = 0x07;
IO初始化时,加这2句就好了。

另外我请问一下那个高低电平初始值的计算和51单片机是一样的吗,我在网上看见好几种算法,以4MHZ晶振频率,1:8预分配为例子。
第一种是:时钟周期为0.25us,指令周期为0.25*4=1us,经过预分频1:8后,指令周期变为8us,TMR1IF溢出为1时需要通过低八位8us*256=2048us,通过高八位2048us*256=524288us,定时器需要524288us溢出,设定0.5s溢出:524288-500000=24288us,指令周期x预分频比=预分频器溢出的周期:1usX8=8us,初始值的时间/预分频器溢出的周期=初始值 :24288us/8us=3036,将其转换为十六进制为0x0BDC;
第二种是:从0加满需要65536个机器周期,每个机器周期等于12个时钟周期,4M晶振每个机器周期为0.25us,每加一个数的机器周期为12*0.25=3us,中断一次耗时50ms,中断20次为1s,50ms的初值计算为:中断值 =(65536-初值)*机器周期,初值=(65536-(50000/3);
不知道哪种算法是对的,第一个的初值网上很少是524288,几乎都是65536;第二个的机器周期等于12个时钟周期不知道这个是以什么为例子,pic单片机是不是机器周期都是等于4个时钟周期?而且第二种1:8分频好像也没有用到。希望大佬能解惑!!!
回复

使用道具 举报

9#
ID:883242 发表于 2024-1-4 15:18 | 只看该作者
1148794250 发表于 2024-1-4 14:38
另外我请问一下那个高低电平初始值的计算和51单片机是一样的吗,我在网上看见好几种算法,以4MHZ晶振频率 ...

这个就不用解惑了吧,你自己用示波器测一下不就知道了吗?如果没有示波器,数LED闪烁个数对比闹钟秒针运动总会吧?
回复

使用道具 举报

10#
ID:1107532 发表于 2024-1-4 15:55 | 只看该作者
Hephaestus 发表于 2024-1-4 15:18
这个就不用解惑了吧,你自己用示波器测一下不就知道了吗?如果没有示波器,数LED闪烁个数对比闹钟秒针运 ...

好的,非常感谢!!!
回复

使用道具 举报

11#
ID:1093268 发表于 2024-1-4 18:14 | 只看该作者
1148794250 发表于 2024-1-4 14:38
另外我请问一下那个高低电平初始值的计算和51单片机是一样的吗,我在网上看见好几种算法,以4MHZ晶振频率 ...

1. PIC16F676的内部RC振荡器FOSC频率是4MHz;
2. 当Timer1的时钟源是内部时钟(FOSC/4)时,即TMR1CS=1。Timer1的时钟源频率就是4MHz/4=1MHz;
3. 所以Timer1自增1的时间是:(1/1MHz) * Timer1预分频比 = 1uS * Timer1预分频比
4. Timer1的中断机制是:溢出中断,也及时TMR1H:TMR1L增加到65535后再加1,就触发中断.
5. 所以Timer1中断时间= 1uS * Timer1预分频比 * (65535 - Timer1初值)。比如要100mS中断一次,可以设置分频比是1:8,初值是53035(0xCF2B),也就是TMR1H=0xCF,TIMR1L=0x2B。
1uS * 8 * (65535 - 53035) = 100000uS = 100mS
PS:PIC16F676的机器周期是4T,并且Timer1的时钟源实际是指令时钟,因此就会有上面的FOSC/4。

评分

参与人数 1黑币 +70 收起 理由
admin + 70 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

12#
ID:1107532 发表于 2024-1-5 08:27 | 只看该作者
哦豁~ 发表于 2024-1-4 18:14
1. PIC16F676的内部RC振荡器FOSC频率是4MHz;
2. 当Timer1的时钟源是内部时钟(FOSC/4)时,即TMR1CS=1。Ti ...

感谢!!!
回复

使用道具 举报

13#
ID:1049963 发表于 2024-5-21 13:15 | 只看该作者
哦豁~ 发表于 2024-1-4 18:14
1. PIC16F676的内部RC振荡器FOSC频率是4MHz;
2. 当Timer1的时钟源是内部时钟(FOSC/4)时,即TMR1CS=1。Ti ...

天才解释,比书上通俗易懂多了,感谢
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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