实验用到8155作为51单片机的IO扩展外设有3*3矩阵键盘,和4位数码管
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
系统方案:
硬件设计
电源电路
电源电路由电源插座,电源开关和电源指示灯组成,其输出为VCC;
电源电路
单片机最小系统
89c51最小系统电路
单片机最小系统:由晶振电路,复位电路,电源电路构成;晶振电路:12MHz的晶振,两个30Pf的瓷片电容连接而成;复位电路:10uf的电解电容,按键开关,1K的电阻连接而成。
8155扩展
8155扩展矩阵电路和数码管
数码管显示驱动电路
4位共阴数码管,由8位的段选端口和4位的位选端口,8位段选端口提供字母,数字,小数点的显示,4位位选端口控制各个数码管的点亮,其低电平有效,数码管的额定工作电流为20mA,PA口的工作电压为5V,所以保证数码管的正常点亮必须接250欧姆的上拉电阻。
3*3矩阵按键电路
由三行三列的按键构成,主要功能的实现在于程序的编写,本实验中用到的行扫描程序,高三位轮流输出低电平,低三位输出高电平,检测低三位的输入电平的变化,如果有变化,则有按键按下,识别出具体的按键位置。
软件设计
定时器0配置
8155的配置
8155的AD0~AD7提供8位地址,CE端口提供8155的IO端口的高8位地址低8位地址:0x00~0x04,分别为命令/状态寄存器,PA口,PB口,PC口;IO/M端口提供8155的工作方式是IO扩展还是RAM扩展。PA口,PB口,PC口的输入还是输出由命令控制寄存器控制;高四位本实验暂时没有用到,所以低四位控制输入输出方式。
按键行扫描
矩阵键盘的6的端口,行端口接PB口的高三位,列端口接PB口的低三位,由于PB口的输入输出方式是分时进行的所以在行扫描过程中要更改8155的命令控制寄存器的内容,改变PB口的IO工作方式,具体为先设置PB口的工作方式为输出方式,接着PB口高三位轮流输出低电平,低三位输出高电平,接着更改PB口的IO方式为输入方式,检测低三位的电平变化,从而检测出具体按键的按下,分别进入功能函数中。
数码管的显示
数码管由8位段选端口和4位位选端口,控制4位位选端口的先后点亮,同时点亮8位段选端口输出其特定的数字,字母,小数点。由于人眼的视觉暂留效应大约为50ms,4位位选端口的先后点亮时间差小于50ms,所以人眼会观察到连续的数字点亮。
电路焊接
仿真结果
电路调试
设计制作中的问题及解决方法
程序流程图:
实验心得体会:
本实验我主要负责程序的编写,首先通过数字秒表的实验,掌握了对一个未知芯片的开发的步骤;本实验中用到的8155芯片,通过查看资料掌握其IO扩展的使用方法,首先对8155的16位地址进行了解,高8位由CE端提供,低八位0x00~0x04,还有就是行扫描键盘程序的编写,本实验3*3矩阵键盘,所以为简便高三位PB4~PB6控制行,PB0~PB2控制列,先让高三位轮流输出低电平:110 ,101,011,低三位输出高电平;后检测低三位的输入电平高低,如果有低电平输入则判断有按键按下;各个按键的控制作用有:1开始记秒2停止3清零,4倒计时设置5倒计时时间设置的加6倒计时时间设置的减7启动倒计时,每个按键的功能都有函数控制。再有就是定时中断的使用,本实验用到定时器0的模式1,定时时间为10ms;数码管的编程方式,首先掌握0~F每个字母数字的真值表,4位共阴数码管有8个段选端口和4个位选端口,8个段选端口控制输出字母数字,位选端口控制那个数码管亮,且位选端口低电平有效。本实验用到的数码管额定电流为20mA,端口输出电压5V,所以上拉电阻的大小为250欧姆。
其次,也懂得学习不仅仅是上课看书,也最重要的是实践将课堂的知识转化为真正的能力,也通过实验学会设计一个硬件系统步骤,设计方案,设计硬件电路,设计程序调试和焊接,最终完成实验;最为重要的是一个团队工作,各自分工大大缩短开发时间。
单片机源程序如下:
- #include<REG51.h>
- #include<ABSACC.h>
- #define COM8155 XBYTE[0X7F00]
- #define PA8155 XBYTE[0X7F01]
- #define PB8155 XBYTE[0X7F02]
- #define PC8155 XBYTE[0X7F03]
- typedef unsigned char uchar;
- typedef unsigned int uint;
- //8051的内部RAM的地址范围为0000H~00FFH
- //A :0X7F01 B:0X7F02 C:0X7F03 定时器低字节 0404H 定时器高字节:0405H
- //命令/状态:0X7F00
- uchar code DIG_CODE[10]={
- 0x3f,0x06,0x5b,0x4f,0x66,
- 0x6d,0x7d,0x07,0x7f,0x6f
- };
- uchar code PCx[4] = {0xee,0xdd,0xbb,0x77};
- sbit IO_M = P2^0;
- sbit CE = P2^7;
- uchar KeyValue=0;
- uchar time1=0,time2=0;
- uint msec = 0;
- static uchar flag=0;
- uint second=0;
- uint CountDownSecond=0;
- uchar c0,c1,c2,c3;
- uchar KeyBoardScan();
- void Delay10ms(uchar s);
- void TimerConfig();
- void digitronDisplay(uint second);
- void Config_8155();
- void operate(uchar KeyValue);
- void Start();
- void Stop();
- void Pause();
- void CountDown();
- void SureStart();
- void main(){
- Config_8155();
- while(1){
- digitronDisplay(second);
- operate(KeyBoardScan());
- }
-
- }
- void Delay10ms(uchar s) //误差 0us
- {
- unsigned char a,b;
- for(s=1;s>0;s--)
- for(b=38;b>0;b--)
- for(a=130;a>0;a--);
- }
- void operate(uchar KeyValue){
- switch(KeyValue){
- case(1):Start();break;//开始
- case(2):Stop();break;//清零
- case(3):Pause();break;//暂停
- case(4):CountDown();break;//倒计时
- }
- }
- void Start(){
- flag=1;
- TimerConfig();
- while(1){
- digitronDisplay(second);
- if(second==10000){
- second=0;
- }
- digitronDisplay(second);
- if(KeyBoardScan()!=1){
- operate(KeyBoardScan());
- }
- }
- }
-
- void Stop(){
- EA=0;//关总中断
- ET0=0;//关定时器0中断
- second = 0;
- CountDownSecond=0;
- while(1){
- digitronDisplay(second);
- operate(KeyBoardScan());
- }
- }
- void Pause(){
- ET0=0;//关定时器0中断
- while(1){
- digitronDisplay(second);
- operate(KeyBoardScan());
- }
-
- }
- void CountDown(){ //设置倒计时时间
- uint a=1;
- while(1){
- if(CountDownSecond<10000&&CountDownSecond>=0){ //显示倒计时定时时间,如果倒计时时间超过范围,倒计时定时时间为0
- digitronDisplay(CountDownSecond);
- }else{
- CountDownSecond=0;
- }
- KeyValue = KeyBoardScan();//获取键盘数字
- switch(KeyValue){
- case(7):{
- CountDownSecond = CountDownSecond + a*100; //秒位加加
- break;
- }//定时间加
- case(8):{
- CountDownSecond = CountDownSecond - a*100;//秒位减减
- break;
- }//定时间减
- case(9):SureStart();break;//启动倒计时
- }
- }
-
- }
- void SureStart(){ //启动倒计时
- flag=2;
- TimerConfig(); //配置定时中断,中断时间为10ms
- while(1){
- digitronDisplay(CountDownSecond);
- if(KeyBoardScan()!=9){
- operate(KeyBoardScan());
- }
- }
- }
- uchar KeyBoardScan(){ //行键盘扫描
- uchar key;
- uchar temp;
- uchar i,j=0;
- for(i=0;i<3;i++){
- COM8155=0x0f; //pb输出
- if(i==0) PB8155 = 0xfe; //11111110
- if(i==1) PB8155 = 0xfd;// 11111101
- if(i==2) PB8155 = 0Xfb; //11111011
- COM8155 = 0X0D; //pb输入
- temp=PB8155; //pb输入读取
- temp=temp&0xf0;
- if(temp!=0xf0){
- Delay10ms(1);
- temp = PB8155;
- temp = temp&0xf0;
- if(temp!=0xf0){
- switch(temp){
- case 0xe0:{
- key = 7-i*3;
- }
- break;
- case 0xd0:{
- key = 8-i*3;
- }
- break;
- case 0xb0:{
- key = 9-i*3;
- }
- break;
- }
- }
- return key;
- }
- }
- return 10;
- }
- void Config_8155(){ //8155芯片的配置
- CE = 0; //片选段,为8155的16位地址提供高8位地址 P2.0~P2.7:1
- IO_M = 1; //作为I/O扩展
- COM8155 = 0X0F; //A,B口做为输出 C口作为输入
- }
- void digitronDisplay(uint second){
- uchar i=0;
- uchar num[4];
- num[3]=second/1000;
- num[2]=second%1000/100;
- num[1]=second%1000%100/10;
- num[0]=second%1000%100%10;
- PA8155=0xff;//消隐
- for(i=0;i<4;i++){
- switch(i){
- case(3): PC8155=0x08;break;
- case(2): PC8155=0x04;break;
- case(1): PC8155=0x02;break;
- case(0): PC8155=0x01;break;
- }
- if(i==2){
- PA8155=~DIG_CODE[num[i]]&0x7f;
- Delay10ms(1);
- PA8155=0xff;//消隐
- }else{
- PA8155=~DIG_CODE[num[i]];
- Delay10ms(1);
- PA8155=0xff;//消隐
- }
- }
- }
- void TimerConfig(){
- TMOD=0x01; //模式设置,00000001,可见采用的是定时器0,工作与模式1(M1=0,M0=1)。
- TR0=1; //打开定时器
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
微控.zip
(215.07 KB, 下载次数: 47)
|