一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 2501|回复: 10
收起左侧

[其他综合] 简单的义隆单片机LED闪烁C程序

[复制链接]
发表于 2015-6-19 19:26 | 显示全部楼层 |阅读模式
朋友要求做一个由15个发光二极管并联组成的闪烁发光装置,要求价格尽量低,用3V纽扣电池供电,没有开关,只有一个按键。找来找去,目前只发现最便宜的8个脚的单片机是义隆的EM78P153B, 0.27元一片,这个价格应该是比较低的了吧。但它是OTP型的,以前没有开发过这个型号,于是在网上看了一些资料,并用C编写了一个程序,经过初步试验,能够满足要求,用CR2540供电,不间断连线开机能够闪烁近200个小时。下面贴出源程序,供有此需求的朋友参考并欢迎指正。源程序有简单的注释和需要注意的地方。开发环境为义隆的eUIDE。

//2015-6-19  按1次,15个发光二极管以120次/秒闪烁,再按1次,熄灭,再按,又闪烁。。。
#include"EM78x153xx.h"

//-----------------------------------------------------------------
     #define DISI()_asm{disi} //禁止中断
     #define WDTC()_asm{wdtc} //清零看门狗定时器
     #define NOP()_asm{nop}
     #define ENI()_asm{eni}   //使能中断
     #define SLEP()_asm{slep} //0-->WDT(清零看门狗),振荡器停止     
//--------------------------------------------------------------
   void _delay_us(unsigned char delay);
   void _delay5ms();     
//-------------------------------------------------------------
        #define key R65     //相当于51 中的位定义
        #define LED R62
//-------------------------------------------------------------   
     unsigned char time_COUNTER;
     unsigned char key_COUNTER;
     
     bit bz_key;            
//--------------------------------------------------------------
        void SysInit(void)
        {       
               P6CR=0x20;   //0B00100000;  //按键设置为输入(P65),其余设为输出(低功耗?)
                        //注意:义隆C编译器不支持2进制!!!                                                  
           PHCR=0xdf;   //0B11011111;  //按键设置为上拉(P65),(注意:送 ”0” 才是使能上拉!)      
         
           led = 0;    //输出为低(led不亮)
           key = 1;    //按键低有效
           
           time_COUNTER=0;  //
           key_COUNTER=0;
           bz_key = 0;   //按一次=1,再按=0
     }     
//====================================================================   
     void main()
        {         NOP();
                NOP();
                NOP();
       
           SysInit();
          
        while(1){          
                  
             //------------------------------------------------------------------------//
             _asm{
               mov a,@0x0f
               contw    //分频比设为1:128,先分配给WDT,(contw=A-->CONT(控制寄存器))
               }
          //------------------------------------------------------------------------//          
            WDTC();       //清零看门狗定时器        
        WDTCR=0;      //禁止WDT   
       PORT6=PORT6;   //读一次要求的电平变化口状态?      
       DISI();        //禁止中断            
       //IMR=0x03;     //开管脚电平变化中断(第1位)和定时器中断(第0位)      
       IMR=0x02;       //开管脚电平变化中断(第1位)
            
      NOP();      
      SLEP();  
      NOP();
      
      //bz_key = 1;   //按一次=1  
      
       WDTC();      //清零看门狗定时器        
       WDTCR=0;     //禁止WDT   
      
      ENI();   //使能中断
     
//////////////////////////////////////////////////////
          _asm{
               mov a,@0x04
               contw    //TCC分频比设为1:32(contw=A-->CONT(控制寄存器))
               }
           TCC=6;       //timer=1/4*(256-6)*32*2=4ms
           
           ISR=0;        //清TCC 中断标志位
//////////////////////////////////////////////////////////////////
               
       IMR=0x01;     //开定时器中断(第0位)              
       
       while(key==0);
       _delay5ms();
       while(key==0);
      
       IMR=0x03; //开管脚电平变化中断(第1位)和定时器中断(第0位)
       
                 while(bz_key==1)
                
                 {      
          IMR=0x03; //开管脚电平变化中断(第1位)和定时器中断(第0位) //TCIE=1;//开定时器中断               
             }
       
                 IMR=0x00;    //TCIE=0;   //关管脚电平变化中断和定时器中断
                 led=0;
       
             //DISI();        //禁止中断
             
             
                while(key==0);
            _delay5ms();
            while(key==0);
            
        }
}
//-------------------------------------------------------------
//=============================================================

void _intcall interrupt(void) @ int         //中断服务程序
{       
        // Write your code (inline assembly or C) here
//-------------------------------------------------       
    if(TCIF==1)        //定时器中断
       {
           ISR&=0XFE;      //清TCC 中断标志位
           TCC=6;          //TCC 赋初值
           time_COUNTER++;
          // if(time_COUNTER>=25)  //25=140次/1秒,120次/1秒=21.4285
           if(time_COUNTER>=21)  //25=140次/1秒,120次/1秒=21.4285            
            {
                time_COUNTER=0;
               
               if(led==1)led=0;
               else led=1;
            }
       }
//--------------------------------------------------
    if(ICIF==1)        //管脚电平中断
     { ICIF=0;
     
   
       //key_COUNTER++;
      if(key==0){ if(bz_key==1) bz_key=0;
                  else bz_key=1;  
                               while(key==1);
                 // _delay5ms();               
                 }

}
        //restore ACC
  //        _asm
  //        {
  //                reti            //Tell Compiler to recover common registers here.
  //                //Don't remove or duplicate this instruction in this function
  //        }
}

//=================================================================

void _intcall interrupt_l(void) @ 0x08:low_int 0  //中断保护程序
{
  //        _asm{
  //                //backup acc, don't remove
  //                mov 0x1F , a
  //        }       
}

//===================================================================

//-------------------------------------------------------------------
void _delay_us(unsigned char delay)
{
        unsigned char i;
       
        for (i=0;i<delay;i++) ;               
}
//-------------------------------------------------------------------
void _delay5ms()
{
        unsigned char i,j;
       
        for (i=0;i<5;i++)     
        {
        for (j=0;j<100;j++) NOP();       
        }
}
/*===================================================================*/
发表于 2015-6-19 19:51 | 显示全部楼层
支持原创。
发表于 2015-6-19 21:17 | 显示全部楼层
OTP的程序怎么写.
要是写错了,扔了再写一片吗?

要是稍大点的工程那不得扔几百片么?
发表于 2015-6-19 21:45 | 显示全部楼层
LED电路都那么复杂···我们初学者怎么混啊···
 楼主| 发表于 2015-6-19 21:59 | 显示全部楼层
junyee 发表于 2015-6-19 21:17
OTP的程序怎么写.
要是写错了,扔了再写一片吗?

otp单片机的程序错了,当然只有扔了,但也有仿真器的,可以仿真好了后,再写入单片机。但义隆仿真器太贵,800多,这个程序相对简单,就没有买仿真器,但由于对管脚电平中断了解不深刻,调试的时候也扔了20几片。好在价格便宜。
 楼主| 发表于 2015-6-19 22:06 | 显示全部楼层
lingshuai2010 发表于 2015-6-19 21:45
LED电路都那么复杂···我们初学者怎么混啊···

用单片机控制led闪烁,电路很简单呀,比用一般元件来搭简单多了,这个是软件,也是很简单的。这个程序调试时用的,有的应该删掉的就没有删。应该删掉。呵呵。
发表于 2015-6-20 15:52 | 显示全部楼层
支持楼主的原创,感觉楼主贴上图更好些!
 楼主| 发表于 2015-6-21 02:27 | 显示全部楼层
本帖最后由 fxhfxh 于 2015-6-21 02:29 编辑
zyh555 发表于 2015-6-20 15:52
支持楼主的原创,感觉楼主贴上图更好些!

QQ图片20150621021316.png
QQ图片20150621021645.png

贴上原理图和pcb,全部贴片元件,pcb为单面板,电池为3伏钮扣电池。用CR2450可以连续工作200个小时,如果用CR2477,将工作更长的时间。


发表于 2015-6-21 09:52 | 显示全部楼层
烧录器几钱啊
 楼主| 发表于 2015-6-21 10:25 | 显示全部楼层

我在淘宝买的750元,加上转换座(因为要烧贴片),也是近800元,感觉还是贵。

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-27 21:50 , Processed in 0.068455 second(s), 47 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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