#include sbit ADC_CS=P1^4;//P1.4引脚重命名 sbit ADC_CLK=P1^5;//P1.5引脚重命名 sbit ADC_DI=P1^6;//P1.6引脚重命名,DI端口和DO端口复用此引脚 sbit beep=P1^7;//P1.7引脚重命名 sbit button=P1^0;//P1.0引脚重命名 sbit led_A=P3^0;//二位数码管的定义 sbit led_B=P3^1; sbit dx_R=P3^2;//东西红绿黄三种led灯的定义 sbit dx_Y=P3^3; sbit dx_G=P3^4; sbit nb_R=P3^7;//南北红绿黄三种led灯的定义 sbit nb_Y=P3^6; sbit nb_G=P3^5; char sec=1;//刷新标志位 char N=25; //定义初始的绿灯倒计时25s unsigned char data1,time=0; char tab_disp[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x80};//共阴极数码管显示 /*视觉停留函数*/ void delay(int t ) {while(t--);} //ADC0832的模拟量读取 int ADC_0832(void) { char i; ADC_CS = 0;//选中芯片,开始工作 ADC_CLK=0; ADC_DI=1; ADC_CLK=1; ADC_CLK=0; //1 down,开始转换 ADC_DI=1; ADC_CLK=1; ADC_CLK=0; // 2 down ADC_DI=0; //选择通道0 ADC_CLK=1; ADC_CLK=0; // 3 down,在下降沿结束前DI输入2位数据用于通道选择,DI端口此时失去作用 ADC_DI=1; // DO端口置1,准备输出数据 ADC_CLK=1; ADC_CLK=0; // 4 down,由D0端输出转换数据最高位 for(i=8;i>0;i--)//循环输出下一位最高数字位 { data1<<=1;//date1左移一位,准备接受输出新的最低位数字 ADC_CLK=0; ADC_CLK=1;//时钟脉冲信号 if(ADC_DI==1) data1|=0x01;//通过DO端口输出数据(0或1),来改变当前date1的最低位数字 ADC_DI=1;//DO端口置1,即单片机读数据前引脚置1 } ADC_CS=1;//转换结束,芯片禁用 return data1; } //初始化中断定时器,保证25ms中刷新一次 void init(void)//声明中断初始化 { EA=1;//中断总开关 TMOD=0x01;//T0方式1 、定时模式 ET0=1;//开定时0中断 TH0=0x9e; //初始值25ms 12M TL0=0x58; TR0=1;//启动定时 } //显示模块,两个数码管显示数据 void display(char dat) { led_A=led_B=0; P2=0XFF;//写入前置1 P2=~tab_disp[dat/10];//显示第一位数据 if(dat/10) led_A=1;//若十位上数字不为0,则显示十位上数字 delay(1000);//第一位数字视觉停留10ms P2=0XFF;//写入前置1 led_A=led_B=0; P2=~tab_disp[dat%10];//显示第二位数据 led_B=1;//显示个位上数字 delay(1000);//第二位数字视觉停留10ms } //处理子函数 void deal(char m) { while(sec) display(m);//调用显示函数 sec=1; } /* 红灯亮15s操作,包括闯红灯和*/ void _red(void) { char i,t; char a,b,c,d,e,f;//状态参数,用于记录中断时南北东西信号灯状态 N=15; //15红灯倒计时 a=dx_R; b=dx_Y; c=dx_G;//各方向信号灯状态送参 d=nb_R; e=nb_Y; f=nb_G; dx_R=1;dx_Y=0;dx_G=0;//各方向信号灯变红 nb_R=1;nb_Y=0;nb_G=0; for(i=N;i>0;i--) { t=60; while(t--)display(i); } dx_R=a; dx_Y=b; dx_G=c;//15s红灯结束,恢复中断时路口信号灯状态 nb_R=d; nb_Y=e; nb_G=f; } /*主函数*/ void main(void) { char i; init();//初始化 while(1) { N=25; dx_R=1;dx_Y=0;dx_G=0;//25s东西红灯,南北25s绿灯 nb_R=0;nb_Y=0;nb_G=1; for(i=N;i>0;i--) { deal(i); } dx_R=1;dx_Y=0;dx_G=0;//5s东西红灯,南北黄灯 nb_R=0;nb_Y=1;nb_G=0; N=5; for(i=N;i>0;i--) { deal(i); } dx_R=0;dx_Y=0;dx_G=1;//25s东西绿灯,南北红灯 nb_R=1;nb_Y=0;nb_G=0; N=25; for(i=N;i>0;i--) { deal(i); } dx_R=0;dx_Y=1;dx_G=0;//5s东西黄灯,南北红灯 nb_R=1;nb_Y=0;nb_G=0; N=5; for(i=N;i>0;i--) { deal(i); } } } //中断服务子程序 void timer0() interrupt 1 using 0 //T0定时 定时25ms { TH0=0x9e;//重载初值 TL0=0x58; time++; if(time==10)//判断是否到0.25s { if(ADC_0832()>153) {beep=0; } else beep=1; //0.25s扫描一次是不是大于3,若大于3则说明闯红灯,蜂鸣器报警 } if(time==40)//判断倒计时是否到1s { sec=0;//刷新标志位置0 time=0;//重新计时1s } if(!button)_red(); //每25ms扫描一次是不是有按键按下 }