参考《51单片机C语言创新教程》温子祺等著。
十多年的房县网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。全网营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整房县建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联公司从事“房县网站设计”,“房县网站推广”以来,每个客户项目都认真落实执行。
源码转自:《51单片机C语言创新教程》。
/*实验名称:交通灯实验
*描 述:交通灯实验要求红灯亮15秒,绿灯亮10秒,黄灯亮5秒,
当红灯切换为绿灯或者绿灯切换为红灯,
要实现灯闪烁。红灯、绿灯、黄灯的点亮持续时间可以通过串口来修改,
并在下一个循环中更新数值。
*作 者:温子祺
*修改日期:2010/5/4
*说 明:代码注释与讲解详见《51单片机C语言创新教程》温子祺等著,北京航空航天大学出版社
*/
#include "stc.h"
typedef unsigned char UINT8;
typedef unsigned int UINT16;
typedef unsigned long UINT32;
typedef char INT8;
typedef int INT16;
typedef long INT32;
#define TIMER0_INITIAL_VALUE 5000
#define HIGH 1
#define LOW 0
#define ON 1
#define OFF 0
#define SEG_PORT P0
#define LS164_DATA(x) {if((x))P0_4=1;else P0_4=0;}
#define LS164_CLK(x) {if((x))P0_5=1;else P0_5=0;}
#define NORTH_R_LIGHT(x) {if((x))P2_0=0;else P2_0=1;}
#define NORTH_Y_LIGHT(x) {if((x))P2_1=0;else P2_1=1;}
#define NORTH_G_LIGHT(x) {if((x))P2_2=0;else P2_2=1;}
#define SOUTH_R_LIGHT(x) {if((x))P2_3=0;else P2_3=1;}
#define SOUTH_Y_LIGHT(x) {if((x))P2_4=0;else P2_4=1;}
#define SOUTH_G_LIGHT(x) {if((x))P2_5=0;else P2_5=1;}
#define TRAFFIC_STATUS_1 0
#define TRAFFIC_STATUS_2 1
#define TRAFFIC_STATUS_3 2
#define UART_MARKER 0xEE
UINT8 Timer0IRQEvent=0;
UINT8 Time1SecEvent=0;
UINT8 Time500MsEvent=0;
UINT8 TimeCount=0;
UINT8 SegCurPosition=0;
UINT8 LightOrgCount[4]={15,5,15,5};
UINT8 LightCurCount[4]={15,5,15,5};
UINT8 TrafficLightStatus=0;
code UINT8 SegCode[10] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
UINT8 SegBuf[4] ={0};
code UINT8 SegPosition[4]={0x07,0x0b,0x0d,0x0e};
typedef struct _LIGHT_VAL
{
UINT8 Head;
UINT8 val[4];
}LIGHT_VAL;
typedef union _LIGHT_VAL_EX
{
LIGHT_VAL lv;
UINT8 p[5];
}LIGHT_VAL_EX;
void LS164Send(UINT8 byte)
{
UINT8 j;
for(j=0;j=7;j++)
{
if(byte(1(7-j)))
{
LS164_DATA(HIGH);
}
else
{
LS164_DATA(LOW);
}
LS164_CLK(LOW);
LS164_CLK(HIGH);
}
}
void RefreshDisplayBuf(UINT8 s1) //刷新显示缓存
{
SegBuf[0] = s1%10;
SegBuf[1] = s1/10;
SegBuf[2] = s1%10;
SegBuf[3] = s1/10;
}
void SegDisplay(void)
{
UINT8 t;
t = SegCode[SegBuf[SegCurPosition]];
SEG_PORT |= 0x0f;
LS164Send(t);
SEG_PORT = (SEG_PORT|0x0f) SegPosition[SegCurPosition];
if(++SegCurPosition=4)
{
SegCurPosition=0;
}
}
void TimerInit(void)
{
TH1 = 0;
TL1 = 0;
TH0 = (65536-TIMER0_INITIAL_VALUE)/256;
TL0 = (65536-TIMER0_INITIAL_VALUE)%256; //定时1MS
TMOD = 0x51; /*01010001 T1计数,T0定时*/
}
void Timer0Start(void)
{
TR0 = 1; //启动计时器1
ET0 = 1;
}
void Timer0Stop(void)
{
TR0 = 0; //启动计时器1
ET0 = 0;
}
void PortInit(void)
{
P0=P1=P2=P3=0xFF;
}
void UartInit(void)
{
SCON=0x40;
T2CON=0x34;
RCAP2L=0xD9;
RCAP2H=0xFF;
REN=1;
ES=1;
}
void UartSendByte(UINT8 byte)
{
SBUF=byte;
while(TI==0);
TI=0;
}
void UartPrintfString(INT8 *str)
{
while(str *str)
{
UartSendByte(*str++);
}
}
void main(void)
{
UINT8 i=0;
PortInit();
TimerInit();
Timer0Start();
UartInit();
RefreshDisplayBuf(LightCurCount[0]);
EA=1;
NORTH_R_LIGHT(ON);
SOUTH_G_LIGHT(ON);
while(1)
{
if(Timer0IRQEvent)
{
Timer0IRQEvent=0;
TimeCount++;
if(TimeCount=200)
{
TimeCount=0;
if(LightCurCount[0])
{
TrafficLightStatus=0;
}
else if(LightCurCount[1])
{
TrafficLightStatus=1;
}
else if(LightCurCount[2])
{
TrafficLightStatus=2;
}
else if(LightCurCount[3])
{
TrafficLightStatus=3;
}
else
{
for(i=0;i4;i++)
{
LightCurCount[i]=LightOrgCount[i];
}
TrafficLightStatus=0;
}
switch(TrafficLightStatus)
{
case 0:
{
NORTH_R_LIGHT(ON);
SOUTH_R_LIGHT(OFF);
NORTH_G_LIGHT(OFF);
SOUTH_G_LIGHT(ON);
NORTH_Y_LIGHT(OFF);
SOUTH_Y_LIGHT(OFF);
}
break;
case 1:
{
if(LightCurCount[1]%2)
{
NORTH_R_LIGHT(ON);
SOUTH_G_LIGHT(ON);
}
else
{
NORTH_R_LIGHT(OFF);
SOUTH_G_LIGHT(OFF);
}
NORTH_Y_LIGHT(ON);
SOUTH_Y_LIGHT(ON);
}
break;
case 2:
{
NORTH_R_LIGHT(OFF);
SOUTH_R_LIGHT(ON);
NORTH_G_LIGHT(ON);
SOUTH_G_LIGHT(OFF);
NORTH_Y_LIGHT(OFF);
SOUTH_Y_LIGHT(OFF);
}
break;
case 3:
{
if(LightCurCount[3]%2)
{
NORTH_G_LIGHT(ON);
SOUTH_R_LIGHT(ON);
}
else
{
NORTH_G_LIGHT(OFF);
SOUTH_R_LIGHT(OFF);
}
NORTH_Y_LIGHT(ON);
SOUTH_Y_LIGHT(ON);
}
break;
default:break;
}
RefreshDisplayBuf(LightCurCount[TrafficLightStatus]);
LightCurCount[TrafficLightStatus]--;
}
SegDisplay();
}
}
}
void UartIRQ(void)interrupt 4
{
static UINT8 cnt=0;
static LIGHT_VAL_EX LightValEx;
if(RI)
{
RI=0;
LightValEx.p[cnt++]=SBUF;
if(LightValEx.lv.Head == UART_MARKER)
{
if(cnt=5)
{
for(cnt=1;cnt5;cnt++)
{
LightOrgCount[cnt-1]=LightValEx.lv.val[cnt];
LightCurCount[cnt-1]=LightValEx.lv.val[cnt];
}
cnt=0;
UartPrintfString("设置交通灯完成\r\n");
}
}
else
{
cnt=0;
}
}
}
void Timer0IRQ(void) interrupt 1
{
ET0 = 0;
TH0 = (65536-TIMER0_INITIAL_VALUE)/256;
TL0 = (65536-TIMER0_INITIAL_VALUE)%256; //定时1MS
Timer0IRQEvent=1;
ET0 = 1;
}
=====================================================================
坐等拿分!
首先你要写中断函数
然后在主程序中像调用子函数一样调用就可以了
举个例子吧
#define uchar unsigned char
#define uchar unsigned char
sbit D1=P1^0;
uchar aa;
void init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void main()
{
init();
while(1)
{
if(aa==20)
{
D1=~D1;
aa=0;
}
}
}
void T0time()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
aa++;
}
三个:
1.总中断使能位EA=1
2.相应中断使能 (ET0、EX0……) 打开
3.中断源:外部中断引脚的电平触发、定时器溢出……
oid PxInt0(void) interrupt 0 //定义外部中断0
void PxInt1(void) interrupt 2 //定义外部中断1
void time0_int(void) interrupt 1 //定义定时器0
void time1_int(void) interrupt 3 //定义定时器1
这里为什么是 0 1 2 3的顺序呢~?其实是单片机内部默认的,顺序依次是:
0 外部中断0
1 定时/计数器0
2 外部中断1
3 定时/计数器1
4 串行口中断
这个是没有什么理由的,记住就行,以后要定义一个中断的时候,定义的是哪一个,就在后面加上它的序号就行了,比如void PxInt0(void) interrupt 0 表示外部中断0,就在后面加上interrupt 0.
逐词解释的话。。。如:void PxInt0(void) interrupt 0
void的意思是没有返回值,Pxint0(void)是你定义的函数名,interrupt表示你定义的是中断函数,0表示你定义的是外部中断0
后面的依此类推。
另外,中断函数不需要在main函数前声明,当单片机检测到中断所需的信号时,它会自动立即停止正在进行的工作进入中断函数。
interrupt
X
其中X表示中断号,
0表示外部中断0
1表示定时器0溢出中断
2表示外部中断1(/INT1)
3表示定时器1溢出中断
4表示串行口中断
5表示定时器2溢出中断
有些增强型51还会有其他中断
标准c语言没有中断调用机制,但是不同编译器都有相应的中断处理方式,可以使用户实现中断功能。
解决方案:
1、采取轮询的方式解决,就是每10毫秒检查一下是否有键盘请求,总的来说,这样基本上可以解决问题,而且简单易行,但每10毫秒都要检查,系统消耗太大。
2、采取中断的方式:
(1)用高级语言调用中断来处理问题。中断是cpu响应一个中断外围设备8259A的一个过程,当键盘敲击,cpu保存断点暂停执行并且跳到相应的中断处理程序继续执行,结束后根据断点再跳回来。通过这种方式可以轻松+愉快地解决这个问题。但是需要用到高级语言调用汇编,根据编译器的不同而有所差别。
(2)自己模拟中断。可以另外建立一个线程专门响应键盘的敲击,如果有敲击则打断主线程。这样做实现起来很复杂,而且涉及到不少复杂的关键技术,比如信号量之类的东西。
3、强大的vc
vc采取了消息映射的机制来处理外部设备的请求,比如时钟中断、键盘中断等等。通过此可以灰常灰常容易的处理外部中断。