单片机课程设计——自动滚动广告牌设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机课程设计
题目:自动滚动广告牌
所在院系:机电汽车工程学院
专业:机101-4班
学号:
姓名:
完成日期:
指导教师:
目录
一、课程设计任务书
二、设计项目简介
(一)设计思路
(二)任务分工
三、设计过程
(一)电路原理图及各器件原理介绍
(二)程序模块
四、程序框图
五、程序清单
六、系统功能简介
(一)产品的功能简介
(二)产品使用方法
(三)产品性能简介
七、产品说明书
八、总结
一、课程设计任务书
基于单片机的自动滚动广告牌的设计
广告牌有四张宣传彩页,卷入一卷轴,依次来回显示每一页,每一页显示的时间相同。

本设计以MCS-51系列单片机为核心,采用常用电子器件设计,自行设计电源。

设计广告彩页的显示时间长度,时间一到就用直流电动机旋转控制彩页切换,用一台直流电动机控制广告彩页的旋转(正转/反转)。

用一个光敏电阻传感器测量光强度,当光线较暗的时候启动背景灯。

设置三个按键:手动/自动切换、手动正转和手动反转,用一个发光二极管显示手动/自动状态。

设置若干个位置控制行程开关,设置彩页的显示位置。

按键输入采用中断方式。

二、设计项目简介
设计思路
(1)选用ATMEL公司的AT89C51单片机。

·与MCS-51 兼容
·4K字节可编程FLASH存储器
·寿命:1000写/擦循环
·数据保留时间:10年
·全静态工作:0Hz-24MHz
·三级程序存储器锁定
·128×8位内部RAM
·32可编程I/O线
·两个16位定时器/计数器
·5个中断源
·可编程串行通道
·低功耗的闲置和掉电模式
·片内振荡器和时钟电路
(2)通过I/O口直接控制广告彩页的切换,通过程序实现显示延时,通过debug确定准确延时时间长度。

(3)通过扫描按键实现监测自动与手动、正转与反转按键状态。

由于选用单片机没有足够的外部中断,且扫描按键的方法更加简洁,故此处违背了设计任务书,希望可以得到谅解。

(4)利用比较器设计光感电路(仿真中使用电位器模拟光敏电阻),提供光线信号。

通过I/O口输出信号,控制背景灯驱动器(仿真中使用74HC573驱动一拍黄色LED小灯模拟),进而控制背景灯开关。

(5)利用L298驱动器驱动直流电机,通过I/O口信号控制L298输出信号,进而控制电机正转,反转及停转的状态。

(6)通过I/O口信号直接控制“手动/自动”状态显示指示灯亮灭。

(7)使用四个行程开关(仿真中使用按键模拟)在自动状态下控制电机正转,
反转及停转。

通过扫描按键的方式实现监测行程开关状态。

(8)设计外部晶振及复位电路。

(9)由于以上任务较简单,较早完成了任务,经过组内商议,为挑战一下自己,决定添加温度检测并显示的功能。

通过DS18b20芯片完成温度检测,A/D转换,使用串口通信单片机将检测的温度读取,经数据转换,并通过I/O口显示在四位共阴极数码管上。

任务分工
分四个工段:独立模块功能单独设计电路、程序,仿真;
各模块整合,调试,仿真;
修整,优化,添加扩展及附加功能;
整理产品说明书、课程报告及其他材料。

分三个小组:
三、设计过程
电路原理图及各器件原理介绍
(1)整体电路图展示
(2)各模块原理介绍
1.光感比较电路
光线越强RV1越小,U3越小,当小到一定值(设定5KΩ)U3<U2。

通过比较器比较U2、U3,U3<U2时输出0,控制背景灯关,U3>U2时输出1,控制背景灯开。

2.DS18b20温度传感器
DSl820数字温度计提供9位(二进制)温度读数,指示器件的温度。

信息经过单线接口送入DSl820或从DSl820送出,因此从主机CPU到DSl820仅需一条线(和地线),DSl820的电源可以由数据线本身提供而不需要外部电源。

DSl820的测量范围从-55到+125增量值为0.5可在l s(典型值)内把温度变换成数字。

每一个DSl820包括一个唯一的64位长的序号,该序号值存放在DSl820内部的ROM(只读存贮器)中,开始8位是产品类型编码(DSl820编码均为10H)接着的48位是每个器件唯一的序号,最后8位是前面56位的CRC(循环冗余校验)码DSl820中还有用于贮存测得的温度值的两个8位存贮器RAM,编号为0号和1号,1号存贮器存放温度值的符号如果温度为负,则1号存贮器8位全为1,否则全为0,0号存贮器用于存放温度值的补码LSB(最低位)的1表示0.5摄氏度,将存贮器中的二进制数求补再转换成十进制数,并除以2就得到被测温度值(-55~125摄氏度)。

3.L298芯片驱动电机
L298N 为SGS-THOMSON Microelectronics 所出产的双全桥步进电机专用驱动芯片( Dual Full-Bridge Driver ) ,内部包含4信道逻辑驱动电路,可同时驱动2个减速直流电机,内含二个H-Bridge 的高电压、大电流双全桥式驱动器,接收标准TTL逻辑准位信号,可驱动46V、2A以下的步进电机,且可以直接透过电
源来调节输出电压;此芯片可直接由单片机的IO端口来提供模拟时序信号,控制转速。

OUTl、OUT2 和OUT3、OUT4之间分别接2个电机;input1~input4 输入控制电位来控制电机的正反转;Enable 则控制电机停转。

4.四位共阴极数码管的驱动
74HC573芯片驱动数码管显示接口,通过单片机I/O接口直接控制数码管位选。

共阴极数码管真值表
十六
0x3f 0x06 0x5b 0x4f 0x66 0x6d 0x7d 0x07 0x7f 0x6f 0x00 0x40
进制
显示
0 1 2 3 4 5 6 7 8 9 空-
符号
74HC573为八进制3 态非反转透明锁存器,输入是和标准CMOS 输出兼容的;加上拉电阻,他们能和LS/ALSTTL 输出兼容。

当锁存使能端LE为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。

当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。

5.独立按键模块
按键一端接地,另一端与单片机I/O口相连并外接上拉电阻。

按键按下时I/O 口由高电位转为低点位,经单片机读取引脚信号,将按键状态输入。

6.外部晶振电路
单片机内部有一个用于构成振荡器的高增益反向放大器,引脚XTAL1为输入
端,XTAL2为输出端。

两个引脚间跨接晶体振荡器与微调电容组成并联谐振电
路,构成一个自激振荡器为内部时钟提供振荡时钟。

振荡期的频率主要取决于晶体的振荡频率,一般晶体可在 1.2MHz~12MHz 之间任选。

电容C1,C2通常取30pF 左右。

7.复位电路
51系列单片机系统通常有上电复位和按键复位两种方式。

最简单的一种上电复位及按键复位电路图如上图所示。

上电后,由于电容充电,使RST 持续一段时间的高电平,完成复位操作;当单片机处于运行中或者死锁时,按下“复位”按钮,也可以使单片机进入复位状态。

程序模块
1. 数码管动态扫描函数
void refresh_led() { P2=Disp_Tab[a[0]];P1=dispbit[0];P1=0xff; //每个数码管按负值、打开、关闭的顺序
P2=Disp_Tab[a[1]];P1=dispbit[1];P1=0xff; P2=Disp_Tab[a[2]] |0x80;P1=dispbit[2];P1=0xff; P2=Disp_Tab[a[3]];P1=dispbit[3];P1=0xff; }
每个数码管依次按负值、打开、关闭的顺序受控,从而实现动态扫描。

2. 温度转换模块程序
void start_temp_sensor(void) { DS18b20_reset(); write_byte(0xCC);
// 发Skip ROM 命令 write_byte(0x44); // 发转换命令
}
/** 读存温度*/ void read_temp() { uint8 temp_data[2]; // 读出温度暂放
uint16 temp=0,c; double wd;
51单片
机 51单片机
start_temp_sensor();
delay_ms(100);
DS18b20_reset(); // 复位
write_byte(0xCC); // 发Skip ROM命令
write_byte(0xBE); // 发读命令
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp = temp_data[1]; //一下三步将温度高八位低八位整合
temp <<= 8;
temp |= temp_data[0];
if (temp_data[1]&0xf0) //判断温度是否为负
{
temp=(~temp)+1; //为负时,取反加一
wd=temp*0.0625; //转为摄氏温度,0.0625为温感芯片储存精度
a[0]=11; //为负时,第一个数码管显示负号}
else
{
wd=temp*0.0625;
a[0]=10; //为正时,第一个数码管不显示}
c=wd; //将摄氏温度转为整型
a[2]=c%10; //第三个数码管显示个位
a[1]=c/10%10; //第二个数码管显示十位
c=wd*10;
a[3]=c%10; //第四个数码管显示小数位
}
3.背景灯控制模块程序
void beijingdeng ()
{
if(ggxh) led_bjd=1;
else led_bjd=0;
}
光感信号为高电平时,背景灯控制引脚输出高电平,控制背景灯关;光感信号为低电平时,背景灯控制引脚输出低电平,控制背景灯亮。

4.自动控制模块程序
void zidong ()
{
led_zs=0; //点亮自动/手动指示灯
while(1)
{
if (i) //判断电机正反转状态,并控制电机正反转
{
dj_zz=1;
dj_fz=0;
}
else
{
dj_zz=0;
dj_fz=1;
}
if (kg1==0) //监测行程开关1状态
{
dj_zz=0; //关闭电机并延时
dj_fz=0;
delay_ms(100);
i++; //控制电机下次启动换向
read_temp(); //读存温度信息
}
if (kg2==0) //监测行程开关2状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
read_temp();
}
if (kg3==0) //监测行程开关3状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
read_temp();
}
if (kg4==0) //监测行程开关4状态
{
dj_zz=0;
dj_fz=0;
delay_ms(100);
i--; //控制电机下次启动换向
read_temp();
}
beijingdeng (); //调入背景灯控制函数,监测感光信号
refresh_led(); //显示温度信息
if(aj_qh==0) //监测自动/手动切换_按键状态
{
dj_zz=0; //监测到切换到手动状态时,电机停转
dj_fz=0;
break; //跳出自动控制循环,进入主函数
}
}
}
自动控制状态下,手动/自动指示灯控制引脚输出为低电平,指示灯亮;判断电机正反转状态,并控制电机正反转;监测行程开关1状态,若为低电平,则关闭电机,延时并控制电机下次启动换向;若为高电平,则不变。

然后读存温度信息并依次监测行程开关2、3状态,若为低电平,则关闭电机,延时并读存温度信息。

然后监测行程开关4状态,若为低电平,则关闭电机,延时并控制电机下次启动换向。

最后监测自动/手动切换_按键状态,若为低电平,则电机停转,跳出自动控制循环,进入主函数。

5.手动控制模块程序
void shoudong () //手动控制子函数
{
led_zs=1; //关闭自动/手动指示灯
while (1)
{
if(aj_zz==0) //按下正转按键时,电机正转
{
dj_zz=0;
dj_fz=1;
}
if(aj_fz==0) //按下反转按键时,电机反转
{
dj_zz=1;
dj_fz=0;
}
if(aj_fz==1&&aj_zz==1) //无按键按下,电机停转
{
dj_zz=0;
dj_fz=0;
}
if(aj_qh==1) //监测自动/手动切换_按键状态
{
break; //监测到切换到自动状态时,跳出手动控制循环,} //进入主函数
refresh_led(); //显示温度信息
beijingdeng (); //调入背景灯控制函数,监测感光信号}
}
手动控制状态下,手动/自动指示灯控制引脚输出为高电平,指示灯灭;若按下正转按键,则L298芯片OUT1输出+12V,OUT2输出0V,电机正转;若按下反转按键,则L298芯片OUT1输出0V,OUT2输出+12V,电机反转;若无按键按下,则L298芯片OUT1输出0V,OUT2输出0V,电机停转。

6.主程序模块程序
main()
{
while(1)
{
if(aj_qh==0) //监测自动/手动切换_按键状态,
{ //并控制进入相应子函数
shoudong();
}
else
{
zidong();
}
}
}
若自动/手动切换_按键按下时,控制引脚输出为低电平,电机状态为手动控制;若自动/手动切换_按键无按下时,控制引脚输出为高电平,电机状态为自动控制。

四、程序框图
五、程序清单
#include <reg52.h>
extern void _nop_ (void);
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
typedef char int8;
typedefint int16;
code uint8 Disp_Tab[] ={ 0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00,0x40};
code uint8 dispbit[4] ={0xfe,0xfd,0xfb,0xf7}; //数码管位选控制变量
uint8 a[4]; //数码管显示控制变量
uint8 i=0; //电机正反转控制变量
#define nops(); {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令,调整控制温感驱动时序
sbitdj_zz = P3^0; //定义电机正反转控制引脚
sbitdj_fz = P3^1;
sbitled_bjd = P3^2; //定义背景灯控制引脚
sbitled_zs = P3^3; //定义指示灯控制引脚
sbit DQ = P3^6; //温度输入口
sbitggxh = P3^7; //定义感光信号引脚
sbit kg1 = P0^0; //定义行程开关1信号引脚
sbit kg2 = P0^1; //定义行程开关2信号引脚
sbit kg3 = P0^2; //定义行程开关3信号引脚
sbit kg4 = P0^3; //定义行程开关4信号引脚
sbitaj_fz = P0^4; //定义电机正反转_按键信号引脚sbitaj_zz = P0^5;
sbitaj_qh = P0^6; //定义自动/手动切换_按键信号引脚/* 数码管动态扫描函数*/
voidrefresh_led()
{
P2=Disp_Tab[a[0]];P1=dispbit[0];P1=0xff; //每个数码管按负值、打开、关闭的顺序
P2=Disp_Tab[a[1]];P1=dispbit[1];P1=0xff;
P2=Disp_Tab[a[2]]|0x80;P1=dispbit[2];P1=0xff;
P2=Disp_Tab[a[3]];P1=dispbit[3];P1=0xff;
}
/*两个延时函数*/
void delay(uint16 n)
{
while (n--);
}
voiddelay_ms(uint16 n)
{
uint8 m=120;
while (n--)
while (m--)
refresh_led(); //刷新显示温度信息
}
/* 18B20复位函数*/
void DS18b20_reset(void)
{
bit flag=1;
while (flag)
{
while (flag)
{
DQ = 1;
delay(1);
DQ = 0;
delay(50); //延时550us
DQ = 1;
delay(6); //延时66us
flag = DQ;
}
delay(45); //延时500us
flag = ~DQ;
}
DQ=1;
}
/** 18B20写1个字节函数*/
voidwrite_byte(uint8 val)
{
uint8i;
for (i=0; i<8; i++)
{
DQ = 1;
_nop_();
DQ = 0;
nops(); //4us
DQ = val& 0x01; //最低位移出
delay(6); //延时66us
val>>= 1; //右移一位
}
DQ = 1;
delay(1);
}
/** 18B20读1个字节函数*/
uint8 read_byte(void)
{
uint8i, value=0;
for (i=0; i<8; i++)
{
DQ=1;
_nop_();
value>>= 1;
DQ = 0;
nops(); //延时4us
DQ = 1;
nops(); //延时4us
if (DQ)
value|=0x80;
delay(6); //延时66us
}
DQ=1;
return(value);
}
/** 启动温度转换*/
voidstart_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC); // 发Skip ROM命令
write_byte(0x44); // 发转换命令
}
/** 读存温度*/
voidread_temp()
{
uint8 temp_data[2]; // 读出温度暂放
uint16 temp=0,c;
doublewd;
start_temp_sensor();
delay_ms(100);
DS18b20_reset(); // 复位
write_byte(0xCC); // 发Skip ROM命令
write_byte(0xBE); // 发读命令
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp = temp_data[1]; //一下三步将温度高八位低八位整合temp<<= 8;
temp |= temp_data[0];
if (temp_data[1]&0xf0) //判断温度是否为负
{
temp=(~temp)+1; //为负时,取反加一
wd=temp*0.0625; //转为摄氏温度,0.0625为温感芯片储存精度
a[0]=11; //为负时,第一个数码管显示负号}
else
{
wd=temp*0.0625;
a[0]=10; //为正时,第一个数码管不显示}
c=wd; //将摄氏温度转为整型
a[2]=c%10; //第三个数码管显示个位
a[1]=c/10%10; //第二个数码管显示十位
c=wd*10;
a[3]=c%10; //第四个数码管显示小数位
}
/*背景灯控制子函数*/
voidbeijingdeng ()
{
if(ggxh) led_bjd=1;
else led_bjd=0;
}
/*自动控制子函数*/
voidzidong ()
{
led_zs=0; //点亮自动/手动指示灯
while(1)
{
if (i) //判断电机正反转状态,并控制电机正反转
{
dj_zz=1;
dj_fz=0;
}
else
{
dj_zz=0;
dj_fz=1;
}
if (kg1==0) //监测行程开关1状态
{
dj_zz=1; //关闭电机并延时
dj_fz=1;
delay_ms(100);
i++; //控制电机下次启动换向
read_temp(); //读存温度信息
}
if (kg2==0) //监测行程开关2状态
{
dj_zz=1;
dj_fz=1;
delay_ms(100);
read_temp();
}
if (kg3==0) //监测行程开关3状态
{
dj_zz=1;
dj_fz=1;
delay_ms(100);
read_temp();
}
if (kg4==0) //监测行程开关4状态
{
dj_zz=1;
dj_fz=1;
delay_ms(100);
i--; //控制电机下次启动换向
read_temp();。

相关文档
最新文档