一个在科技节上的小制作交通信号灯仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h> //调用单片机头文件
- #define uchar unsigned char //宏定义"uchar"代替"unsigned char"。
- #define uint unsigned int //宏定义"uint"用来定义无符号整型数。
- #define LED_a 0 //数码管段选的a段接在段选IO口的第0位
- #define LED_b 1
- #define LED_c 2
- #define LED_d 3
- #define LED_e 4
- #define LED_f 5
- #define LED_g 6
- #define LED_dp 7
- uchar code DisplayOther[]={
- 0xff, //0 空
- 0x7f, //1 "."
- 0xbf, //2 "-"
- 0xa7 //3 c
- };
- //数码管段选定义 0 1 2 3 4 5 6 7 8 9
- uchar code smg_du[10] = {
- 0xc0, //0
- 0xf9, //1
- 0xa4, //2
- 0xb0, //3
- 0x99, //4
- 0x92, //5
- 0x82, //6
- 0xf8, //7
- 0x80, //8
- 0x90, //9
- };
- uchar dis_smg[4] = {0xc0,0xf5,0x8c,0x94};
- //数码管位选定义
- sbit smg1 = P2^0; //东西数码管2
- sbit smg2 = P2^1; //东西数码管1
- sbit smg3 = P2^2; //南北数码管2
- sbit smg4 = P2^3; //南北数码管1
- char count = 0; //东西 南北 倒计时变量
- sbit nb_red = P1^0; //南北红灯
- sbit nb_green = P1^2; //南北绿灯
- sbit nb_yellow = P1^1; //南北黄灯
- sbit dx_red = P1^3; //东西红灯
- sbit dx_green = P1^5; //东西绿灯
- sbit dx_yellow = P1^4; //东西黄灯
- uchar flag_jtd_mode; //交通灯的模式 根据时间
- bit flag_1s = 1; //进入南北方向切换的标志位
- bit flag_500ms;
- bit flag_dx_nb; //东西南北模式
- uchar flag_5m_value;
- uchar dx_time = 30,nb_time = 30; //东西、南北的时间
- uchar flag_jdgz ; //交通管制
- /********************************************************************
- * 名称 : uchar ChangeFor(uchar dat)
- * 功能 : 交换一个字节位的位置,用于数码管显示
- * 输入 : 需要改变的数
- * 输出 : 改变后的数
- ***********************************************************************/
- uchar ChangeFor(uchar dat){
- uchar temp=0;
- if(dat&0x01)
- temp|=0x01<<LED_a;
- if(dat&0x02)
- temp|=0x01<<LED_b;
- if(dat&0x04)
- temp|=0x01<<LED_c;
- if(dat&0x08)
- temp|=0x01<<LED_d;
- if(dat&0x10)
- temp|=0x01<<LED_e;
- if(dat&0x20)
- temp|=0x01<<LED_f;
- if(dat&0x40)
- temp|=0x01<<LED_g;
- if(dat&0x80)
- temp|=0x01<<LED_dp;
- return temp;
- }
- /***********************数码管位选函数*****************************/
- void smg_we_switch(uchar i){
- switch(i){
- case 0: smg1 = 0; smg2 = 1; smg3 = 1; smg4 = 1; break;
- case 1: smg1 = 1; smg2 = 0; smg3 = 1; smg4 = 1; break;
- case 2: smg1 = 1; smg2 = 1; smg3 = 0; smg4 = 1; break;
- case 3: smg1 = 1; smg2 = 1; smg3 = 1; smg4 = 0; break;
- }
- }
- /****************************延时1ms函数****************************/
- void delay_1ms(uint q){
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<110;j++);
- }
- /***************************数码管显示函数*****************************/
- void DisplayScan(){
- static uchar i;
- {
- {
- P0 = 0xff; //消隐
- smg_we_switch(i); //位选
- P0 = ChangeFor(dis_smg[i]); //段选
- delay_1ms(3);
- }
- i++;
- if(i>=4)
- i=0;
- }
- }
- /*********************定时器0、定时器1初始化******************/
- void time0_init(){
- TMOD = 0x01; //设置定时器0为工作模式1 (16-bit)
- TL0 = 15536; //给定时器低位赋初始值 65536-15536=50000us=50ms,即50ms一个中断
- TH0 = 15536 >> 8; //给定时器高位赋初始值
- TR0 = 1; //开启定时器0
- ET0 = 1; //允许定时器0中断
- EA = 1; //开启全局中断
- }
- /*********************交通灯处理函数*********************************/
- void traffic_light_dispose(){
- if(flag_1s == 1){//如果切换标志为1
- flag_1s = 0; //清零标志位
- if(count == 0){
- if(flag_dx_nb == 1)
- count = nb_time; //南北时间
- else
- count = dx_time; //东西时间
- flag_dx_nb = ~flag_dx_nb; //切换南北时间
- }
- count --;
- }
- /***********************南北时间*********************************/
- if(flag_dx_nb == 0){
- if(count > 3){
-
- dis_smg[0] = smg_du[count % 10] ;
- dis_smg[1] = smg_du[count / 10] ;
- dis_smg[2] = smg_du[(count-3) % 10] ;
- dis_smg[3] = smg_du[(count-3) / 10] ;
- dx_red = 1; //灭
- dx_yellow = 1; //灭
- nb_green = 1; //灭
- nb_yellow = 1; //灭
- dx_green = 0; //亮
- nb_red = 0; //亮
- flag_5m_value = 0;
- }
- else if(count <= 3){ //当小于3秒时 黄灯闪烁
- dis_smg[0] = smg_du[count % 10] ;
- dis_smg[1] = smg_du[count / 10] ;
- dis_smg[2] = smg_du[count % 10] ;
- dis_smg[3] = smg_du[count / 10] ;
- dx_red = 1; //灭
- dx_green = 1; //灭
- nb_green = 1; //灭
- nb_yellow = 1; //灭
- nb_red = 0; //亮
-
- if(flag_500ms == 0){ //黄灯闪烁
- dx_yellow = 0;//亮
- }
- else{
- dx_yellow = 1;//灭
- }
- }
- }
-
- /***********************东西时间*********************************/
- if(flag_dx_nb == 1){
- if(count > 3){
-
- dis_smg[0] = smg_du[(count-3) % 10] ;
- dis_smg[1] = smg_du[(count-3) / 10] ;
- dis_smg[2] = smg_du[count % 10] ;
- dis_smg[3] = smg_du[count / 10] ;
-
- dx_red = 0; //亮
- nb_green = 0; //亮
- nb_yellow = 1; //灭
- dx_green = 1; //灭
- dx_yellow = 1; //灭
- nb_red = 1; //灭
- flag_5m_value = 0;
- }
- else if(count <= 3){ //当小于3秒时 黄灯闪烁
-
- dis_smg[0] = smg_du[count % 10] ;
- dis_smg[1] = smg_du[count / 10] ;
- dis_smg[2] = smg_du[count % 10] ;
- dis_smg[3] = smg_du[count / 10] ;
- dx_red = 0; //灭
- dx_green = 1; //灭
- dx_yellow = 1; //灭
- nb_red = 1; //灭
- nb_green = 1; //灭
-
- if(flag_500ms == 0){ //黄灯闪烁
- nb_yellow = 0; //亮
- }
- else{
- nb_yellow = 1; //灭
- }
- }
- }
- }
- uchar key_can; //按键值
- //按键定义
- sbit Key1=P1^6; //设置键
- sbit Key2=P1^7; //加按键
- sbit Key3=P3^2; //减按键
- sbit Key4=P3^3; //交通管制键
- //========================================================================
- // 函数: uchar Key_Scan()
- // 应用: temp=uchar Key_Scan();
- // 描述: 按键扫描并返回按下的键值
- // 返回: 按下的键值
- // 日期: 2019-03-31
- // 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
- //========================================================================
- uchar Key_Scan(){
- static uchar key_up=1;//按键松开标志
- if(key_up&&(Key1==0||Key2==0||Key3==0||Key4==0)){
- delay_1ms(10);//去抖动
- key_up=0;
- if(Key1==0) return 1;
- else if(Key2==0)return 2;
- else if(Key3==0)return 3;
- else if(Key4==0)return 4;
- }
- else if(Key1==1&&Key2==1&&Key3==1&&Key4==1)
- key_up=1;
- return 0;// 无按键按下
- }
- uchar menu_1;//纵横加减标示
- /********************设置函数*****************/
- void setting(){
- if(key_can == 4){ //交通管制按键
- flag_jdgz ++;
- if(flag_jdgz > 5)
- flag_jdgz = 0;
- if(flag_jdgz == 1){ // 全部亮红灯
- dx_red = 0; //亮
- nb_red = 0; //亮
- dx_green = 1; //灭
- dx_yellow = 1; //灭
- nb_green = 1; //灭
- nb_yellow = 1; //灭
- }
- if(flag_jdgz == 2){ // 全部亮黄灯
- dx_red = 1; //灭
- dx_green = 1; //灭
- nb_red = 1; //灭
- nb_green = 1; //灭
- nb_yellow = 0; //亮
- dx_yellow = 0; //亮
- }
- if(flag_jdgz == 3){ // 全部亮绿灯
- dx_green = 0; //亮
- nb_green = 0; //亮
- dx_red = 1; //灭
- dx_yellow = 1; //灭
- nb_red = 1; //灭
- nb_yellow = 1; //灭
- }
- if(flag_jdgz == 4){ // 东西绿灯 南北红灯
- dx_red = 0; //亮
- nb_green = 0; //亮
- dx_green = 1; //灭
- dx_yellow = 1; //灭
- nb_red = 1; //灭
- nb_yellow = 1; //灭
- }
- if(flag_jdgz == 5){ // 南北绿灯 东西红灯
- dx_green = 0; //亮
- nb_red = 0; //亮
- dx_red = 1; //灭
- dx_yellow = 1; //灭
- nb_green = 1; //灭
- nb_yellow = 1; //灭
- }
- }
-
- if(key_can == 1){ //设置键
- menu_1 ++;
- if(menu_1 >= 3){
- menu_1 = 0;
- }
- }
- if(menu_1 == 1){ //设置东西的时间
- if(key_can == 2){
- dx_time ++ ; //加1
- if(dx_time > 99) //时间最大值为99s
- dx_time = 99;
- }
- if(key_can == 3){
- dx_time -- ; //减1
- if(dx_time <= 5) //时间最小值为5s
- dx_time = 5;
- }
- dis_smg[0] = smg_du[(dx_time-1) % 10] ;
- dis_smg[1] = smg_du[(dx_time-1) / 10] ;
- dis_smg[2] = DisplayOther[2] ;
- dis_smg[3] = DisplayOther[2] ;
- }
-
- if(menu_1 == 2){ //设置南北的时间
- if(key_can == 2){
- nb_time ++ ; //加1
- if(nb_time > 99) //时间最大值为99s
- nb_time = 99;
- }
- if(key_can == 3){
- nb_time -- ; //减1
- if(nb_time <= 5) //时间最小值为5s
- nb_time = 5;
- }
- dis_smg[0] = DisplayOther[2] ;
- dis_smg[1] = DisplayOther[2] ;
- dis_smg[2] = smg_du[(nb_time-1) % 10] ;
- dis_smg[3] = smg_du[(nb_time-1) / 10] ;
- }
- }
- /*********************************主函数********************************/
- void main(){
- time0_init();
- while(1){
- key_can=Key_Scan();
- if(key_can)
- setting();
- if((menu_1 == 0) && (flag_jdgz == 0))
- traffic_light_dispose();
- DisplayScan();
- }
- }
- /*********************定时器0中断服务程序************************/
- void time0_int() interrupt 1 {
- static uchar value; //定时10ms中断一次
- TL0 = 15536; //给定时器低位重装初始值 65536-15536=50000us=50ms,即50ms一个中断
- TH0 = 15536 >> 8; //给定时器高位重装初始值
- value ++;
- flag_5m_value++;
- if(flag_5m_value % 10 == 0)
- flag_500ms = ~flag_500ms;
- if(value >= 20){
- value = 0;
- flag_1s = 1;
- }
- }
复制代码
所有资料51hei提供下载:
科技节——基于51单片机的交通灯项目.zip
(1.41 MB, 下载次数: 94)
|