钻石会员
主题
帖子
积分19886
阅读权限50
注册时间2009-4-2
最后登录1970-1-1
在线时间 小时
|
朋友要求做一个由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();
}
}
/*===================================================================*/ |
|