一、简介
近来学(玩)了下已经好久没碰的51,心血来潮自己DIY了一个交通信号灯模型。没有什么创新之处,就是复(dao)习(gu)复(dao)习(gu)了下51的定时器中断、外部中断以及最小系统电路,熟悉了下74HC595的用法和数码管。因为好久没碰51了导致数码管的顺序记反了 懒得再改电路了,于是将错就错就按反着的顺序搞下去了。由于快考试了事情也比较多,基本是隔三差五得做,时间战线拉得比较长。。。当然这些都无关紧要了,主要还是培养下自己分文件模块化编程的习惯嘛,文件分的比较细致,看上去舒服 .
因为是完全自己设计的嘛难免很多疏漏之处。当然由于这个电路比较简单方案和其他人雷同了也是正常现象,说明英雄所见略同嘛~ 。在此开源大家共同学习,希望各路大神能指点迷津,欢迎大家来喷~~~~
废话不多说了。先介绍下功能:
1)为了可拓展性,我将单片机所有的引脚全部引出,后期可拓展或改做它用,每个IO引出两排排针接线更舒服。
2)为了后期如果能做其他实验不产生干扰,外围电路基本全部采用杜邦线接线,不直接接在IO上了。其中595的VCC放置了一个跳线帽作为VCC供电。
3)本人本着尽量少地用飞线地原则,能往正面跳就先跳线,但是到了2位数码管空间不算多了,也做的比较累了,就偷懒全用了飞线。
4)晶振用了12MHz插在了单片机旁。采用12MHz地原因是定时器时间好计算,没用串口不需要很精确地波特率。插在外面没焊死仅仅因为板子空间不够了,而我不像飞线。。。
5)因为东西向的灯是同步的,南北向的灯也是同步的,所以一个方向上的三色交通灯我选择了分别并联的方式,没全部并联是斟酌了下IO的驱动能力和后期的可拓展性还有一定条件下节省IO接口,故总共用了6个IO口控制交通灯,欢迎大家来喷~~~
6)本次模拟仅为理想情况,以一分钟为一周期红绿交替指示。在还剩3秒时黄灯闪烁,当然也是为了简化程序所有的黄灯一起闪。
7)通过外部中断选择工作/休息模式。休息模式下所有LED(包括数码管)同步闪烁,直到将拨盘开关拨回(有延误时间。。。)。
想到的大概就这么多吧,详细功能不介绍了,直接上代码参考。
二、原理图
元件清单:
STC89C52RC x1
74HC595 x1
10K排阻 x1
12Mhz晶振 x1
选择开关 x1
独立按键 x1
30pF电容 x3
10K电阻 x1
1K电阻 x1
220Ω电阻 x20
红色LED x3
黄色LED x3
绿色LED x3
2位数码管 x1
proteus 8 仿真原理图
三、部分源程序
程序基于Keil 5 C语言编写,部分程序有注释
1.文件结构
所有头文件均放置在USER_Config.h头文件中
main.c 主函数
it.c 中断服务函数
delay.c 延时函数
74HC595.c 595驱动函数
LED.c 交通灯
SEG.c 数码管
2.头文件
USER_Config.h
/******************************************
USER HEARD 2017/6/4
*******************************************/
#ifndef _USERCONFIG_H_
#define _USERCONFIG_H_
/* 定义数据类型 */
#define uchar unsigned char
#define uint unsigned int
#define NOP() _nop_()
#include
#include
#include "interrupt.h"
#include "delay.h"
#include "74HC595.h"
#include "SEG.h"
#include "LED.h"
/* 宏定义引脚 */
#define SEG P0
#define LEDs P2
/* 74HC595驱动 */
sbit S_CLK = P1^0;
sbit R_CLK = P1^1;
sbit MOSIO = P1^2;
/* 数码管位选 */
sbit SEG1 = P0^0;
sbit SEG2 = P0^1;
/* 交通灯 */
sbit XR = P2^0;
sbit XY = P2^1;
sbit XG = P2^2;
sbit YR = P2^3;
sbit YY = P2^4;
sbit YG = P2^5;
/* 选择开关 */
sbit SW = P3^2;
#endif
其他头文件大同小异就不贴了。
3.it.c
/******************************************
中断服务程序
by LZK 2017/6/17
******************************************/
#include "USER_Config.h"
uint Num_Min = 0;//分钟计数器
uchar Num_Sec = 0;//秒钟计数器
uchar Number = 60;//计数器
uchar Mark = 0;//标记
void Timer_Init()
{
TMOD = 0x11;//定时器0定时器1为工作方式1
/* 装载初值 */
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
EA = 1;//开总中断
/* 开启定时器中断 */
ET0 = 1;//定时器0
ET1 = 1;//定时器1
/* 启动定时器 */
TR0 = 1;//定时器0
TR1 = 1;//定时器1
/* 外部中断 */
EX0 = 1;
IT0 = 0;
}
void Int0_Select() interrupt 0
{
Num_Min = 0;
Num_Sec = 0;
Number = 60;
Mark = 0;
Calculate(Number);
LED_Relax();
}
void T0_Time() interrupt 1
{
/* 重装初值 */
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
Num_Sec++;
if(Num_Sec==20)
{
Num_Sec = 0;
Number--;
Calculate(Number);
}
}
void T1_Time() interrupt 3
{
/* 重装初值 */
TH1 = (65536-50000)/256;
TL1 = (65536-50000)%256;
Num_Min++;
if(Num_Min==60*20)
{
Num_Min = 0;
Number = 60;
Mark = ~Mark;
}
}
4.delay.c
/*************************************
延时函数库 By LZK
频率:12MHz
*************************************/
#include "USER_Config.h"
/* 延时x*9us */
void delay_8us(uint x)
{
uint i,j;
for(i=0;i
/*************************************
595发送数据 By LZK
频率:12MHz
2017/6/5
*************************************/
#include "USER_Config.h"
void HC595SendData(uchar SendVal)
{
unsigned char i;
for(i=0;i<8;i++)
{
MOSIO=SendVal>>7;
SendVal<<=1;
S_CLK=0;
NOP();
NOP();
S_CLK=1;
}
R_CLK=0;
NOP();
NOP();
R_CLK=1;
}
6.LED.c
/**********************************
LEDs Control
控制交通灯
by LZK 2017/6/17
**********************************/
#include "USER_Config.h"
extern uchar Number;
extern uchar Mark;
void LED_Init()
{
LEDs = 0xff;
//SW = 0;
}
void Select()
{
uchar sw = SW;
switch(sw)
{
case 0:
LED_Relax();
break;
case 1:
LED_Control();
break;
}
}
void LED_Relax()
{
uint x = 10000;
SEG = 0xff;
LEDs = 0xff;
while(x--)
HC595SendData(~0x00);
x = 10000;
SEG = 0x00;
LEDs = 0x00;
while(x--)
HC595SendData(~0x00);
}
void LED_Control()
{
/* 黄灯判断 */
if(Number <= 3)
{
XY=~XY;
YY=~YY;
delay(100);
}
else
{
XY = 1;
YY = 1;
}
/* 路口选择 */
XR = Mark;
XG = ~Mark;
YR = ~Mark;
YG = Mark;
/* 显示 */
Display();
}
7.SEG.c
/*************************************
数码管显数 By LZK
频率:12MHz
2017/6/5
*************************************/
#include "USER_Config.h"
uchar code NUM[]={0x3f,0x30,0x6d,0x79,0x72,0x5b,0x5f,0x31,0x7f,0x7b,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar value[2];
void Calculate(uint num)
{
value[0] = num%10;
value[1] = num/10;
}
void Display()
{
//发送十位数
HC595SendData(NUM[value[1]]);
SEG = 0x01;
delay_8us(25);
//消隐
HC595SendData(0x00);
delay_8us(25);
//发送个位数
HC595SendData(NUM[value[0]]);
SEG = 0x02;
delay_8us(25);
//消隐
HC595SendData(0x00);
delay_8us(25);
}
8.main.c
/*************************************************
交通信号灯 by LZK
Date:2017/6/4
通过定时器0读秒,通过定时器1换方向
通过Calculate传送数字
**************************************************/
#include
#include "USER_Config.h"
extern uchar Number;
void main()
{
Timer_Init();
LED_Init();
while(1)
{
LED_Control();
}
}
四、成果展示
五、总结
第一次发博客,如有不妥的地方请大家多指教
网盘分享:
链接:http://pan.baidu.com/s/1skIP6f7 密码:1eey