找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1972|回复: 15
收起左侧

一个简单的单片机入门程序,用C编写.不知道错在哪?希望大佬指点

[复制链接]
ID:526188 发表于 2019-5-2 22:31 | 显示全部楼层 |阅读模式
   利用P1口输出高低电平,控制继电器的开合,以实现对外部装置的控制。
1)利用定时计数器0定时0.5秒,在定时时间到时,通过P1.2控制继电器每隔0.5秒通断1次,以便控制LED灯的闪烁。
         2)利用定时计数器1设置为计数模式,通过P3.5所接的按钮开关给出计数脉冲,每检测到一个脉冲,控制继电器通断1次,以便切换连接在P1.2引脚的LED灯状态。
  我的理解:继电器只是个幌子,其实就是一个LED灯,上面两个要求分开来用两个程序做我都能实现,问题是放到一个程序中再仿真,什么现象也没有.
总程序如下,不知道错在哪,希望大佬指点
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int

sbit P1_0=P1^0;
sbit P3_5=P3^5;
void delayms(uint xms)
{
        uint i,j;
        for(i=0;i<xms;i++)
                for(j=0;j<110;j++) ;
}

void main(void)
{
        TMOD=0x61;                                   //置定时器0工作方式1,计数器1工作方式2

        TH0=0x3c;                                   //设置计数初值,定时100ms
        TL0=0xae;
        TH1=0xff;                                   //计数1个脉冲
        TL1=0xff;
        
        EA=1;                                              //开中断
        ET0=0;                                           //关定时器0中断
        ET1=1;                                           //开计数器1中断

        TF0=0;                                           //清除TF0标志位
        TF1=0;                                           //清除TF1标志位
        TR0=1;                                           //启动定时器0
        TR1=1;                                           //启动计数器1
        while (1)
        {
                if(TF0)
                {
                   TF0=0;                                           //清除TF0标志位
                   TH0=0x3c;                                   //重装初值,定时100ms
               TL0=0xae;
                   P1_0=!P1_0;
                }
        }

}

void service_int1()interrupt 3 using 3
{
        P1_0=!P1_0;                                   //自动装初值
}         

回复

使用道具 举报

ID:526188 发表于 2019-5-2 22:33 | 显示全部楼层
本帖最后由 单片机新手375 于 2019-5-2 22:35 编辑

重新附上程序,看得清楚点
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int

sbit P1_0=P1^0;
sbit P3_5=P3^5;
void delayms(uint xms)
{
        uint i,j;
        for(i=0;i<xms;i++)
                for(j=0;j<110;j++) ;
}

void main(void)
{
        TMOD=0x61;  //置定时器0工作方式1,计数器1工作方式2

        TH0=0x3c;     //设置计数初值,定时100ms
        TL0=0xae;
        TH1=0xff;             //计数1个脉冲
        TL1=0xff;
        
        EA=1;         //开中断
        ET0=0;         //关定时器0中断
        ET1=1;         //开计数器1中断

        TF0=0;         //清除TF0标志位
        TF1=0;        //清除TF1标志位
        TR0=1;         //启动定时器0
        TR1=1;         //启动计数器1
        while (1)
        {
                if(TF0)
                {
                   TF0=0;          //清除TF0标志位
                   TH0=0x3c;    //重装初值
                  TL0=0xae;
                   P1_0=!P1_0;
                }
        }

}

void service_int1()interrupt 3 using 3
{
        P1_0=!P1_0;            //自动装初值
}         
回复

使用道具 举报

ID:525872 发表于 2019-5-3 20:39 | 显示全部楼层
中断入口必须重新装载初值
回复

使用道具 举报

ID:525872 发表于 2019-5-3 20:40 | 显示全部楼层
中断入口程序需要重新装载值,TH1,TL1
回复

使用道具 举报

ID:185385 发表于 2019-5-3 20:46 | 显示全部楼层
你那个定时器查询应该括号内加个感叹号,然后仿真一下。
回复

使用道具 举报

ID:213173 发表于 2019-5-4 07:06 | 显示全部楼层
本帖最后由 wulin 于 2019-5-4 08:15 编辑


无标题.jpg
  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. sbit P1_0=P1^0;
  5. sbit P3_5=P3^5;
  6. /*
  7. void delayms(uint xms)
  8. {
  9.         uint i,j;
  10.         for(i=0;i<xms;i++)
  11.                 for(j=0;j<110;j++) ;
  12. }*/
  13. uchar i=0;  //计数变量
  14. bit flag=1;//中断标志

  15. void main(void)
  16. {
  17.         TMOD=0x61;  //置定时器0工作方式1,计数器1工作方式2
  18.        
  19.         TH0=0x3C;        //设置定时初值,定时50ms
  20.         TL0=0xB0;
  21. //        TH0=0x3c;     //设置计数初值,定时100ms
  22. //        TL0=0xae;
  23.         TH1=0xff;             //计数1个脉冲
  24.         TL1=0xff;
  25.        
  26.         EA=1;         //开中断
  27.         ET0=0;         //关定时器0中断
  28.         ET1=1;         //开计数器1中断
  29.        
  30.         TF0=0;         //清除TF0标志位
  31.         TF1=0;        //清除TF1标志位
  32.         TR0=1;         //启动定时器0
  33.         TR1=1;         //启动计数器1

  34.         P1_0=0;

  35.         while (1)
  36.         {
  37.                 if(TF0)
  38.                 {
  39.                         TF0=0;        //清除TF0标志位
  40.                         TH0=0x3C;    //重装初值
  41.                         TL0=0xB0;               
  42. //                        TH0=0x3c;    //重装初值
  43. //                        TL0=0xae;
  44.                         i++;
  45.                         if(i>=10)        //0.5秒
  46.                         {
  47.                                 i=0;
  48.                                 if(flag)
  49.                                         P1_0=~P1_0;
  50.                                 else
  51.                                         P1_0=0;
  52.                         }
  53.                 }
  54.         }
  55. }

  56. void service_int1()interrupt 3 using 3
  57. {
  58.         flag=~flag;            //自动装初值
  59. }
复制代码





回复

使用道具 举报

ID:526827 发表于 2019-5-4 10:52 来自手机 | 显示全部楼层
楼主,中断入口程序需要重新装载初值,TH1,TL1
回复

使用道具 举报

ID:525872 发表于 2019-5-4 12:03 | 显示全部楼层
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int

sbit P1_2=P1^2;
sbit P3_5=P3^5;

uchar count=0;//脉冲次数
void int0(void)//中断计数/定时器0 初始化
{
        TMOD=0X50;//定时器1方式1
       //方式0 13位 8192,最大定时8.192ms;方式1 16位,65536,最大定时65.536ms,不能直接定时100ms
       //方式2 自动装载8位
        TH1=(65536-1000)/256;        //整除得高位  如12/10=1        定时1ms
        TL1=(65535-1000)%256 ;        //取余得低位   如12%10=2  定时1ms
      //计算按键脉冲数数:在定时器计数每50us(定时越小越好,检测越频繁)检测下检测按键脉冲次数
        EA=1;//开总中断
        ET1=1;TR1=1;//定时器1开启定时中断标志
}

void main(void)
{
        int0();//  定时器0/定时器1中断初始化   
        while (1);
}

void service_int1()interrupt 3  //定时器1定时/计数入口
{
        TH1=(65536-1000)/256;//重新装载定时初值  
        TL1=(65535-1000)%256 ;       
        uchar i=0;
        i++;
        if(i==500)    //0.5s=500ms=1ms*500,500次中断即为500ms
         {
          P1_2=~P1_2;
          //取反实现0.5s闪烁;刚开始默认P1_2为1,直接接led则灯灭,接继电器则灯是亮

          i==0;  
         }
       if(P3_5==0)//脉冲检测
         {
           delayms(10); //按键消抖10ms
           if(P3_5==0)//再次确认是否被按下
             {
              count++;//计数按键脉冲次数,自加一次
              P1_2=0; //按键未松开则常亮
              while(!P3_5);//按键松开检测
              i==0;
             }
         }
}
//如有疑问请加qq答疑1124485718;同时启动两个定时计数是不合理的,中断有优先级,除非关闭另一个中断
回复

使用道具 举报

ID:467275 发表于 2019-5-4 19:16 | 显示全部楼层

楼主,中断入口程序需要重新装载初值,TH1,TL1
回复

使用道具 举报

ID:526188 发表于 2019-5-5 09:08 | 显示全部楼层
18312284784 发表于 2019-5-3 20:40
中断入口程序需要重新装载值,TH1,TL1

方式2不是可以自动重装初值吗?
我一个用的查询方式,一个用的中断方式应该不冲突吧,不是很懂....
回复

使用道具 举报

ID:526188 发表于 2019-5-5 09:09 | 显示全部楼层
白羊一只老母猪 发表于 2019-5-3 20:46
你那个定时器查询应该括号内加个感叹号,然后仿真一下。

书上的都没加,他这是判断为1才执行吧
回复

使用道具 举报

ID:526188 发表于 2019-5-5 09:14 | 显示全部楼层

为什么给TH0,TL0赋值两次?
还有if(1>=10)那一块看不懂,中断程序里面为什么只有flag
回复

使用道具 举报

ID:260597 发表于 2019-5-5 16:24 | 显示全部楼层
楼主,中断入口程序需要重新装载初值,TH1,TL1
回复

使用道具 举报

ID:526188 发表于 2019-5-7 08:01 | 显示全部楼层
877140465 发表于 2019-5-5 16:24
楼主,中断入口程序需要重新装载初值,TH1,TL1

重装了,还是不行,再说方式2应该是自动装初值吧(书上写的)
回复

使用道具 举报

ID:528288 发表于 2019-5-7 08:47 | 显示全部楼层
很好的学习资料
回复

使用道具 举报

ID:213173 发表于 2019-5-7 08:48 | 显示全部楼层
单片机新手375 发表于 2019-5-5 09:14
为什么给TH0,TL0赋值两次?
还有if(1>=10)那一块看不懂,中断程序里面为什么只有flag

如果我给你改好的程序你只是粗略的看一眼,根本就没有试,甚至把 i 看成1,我就没有兴趣做多余的解释了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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