单片微机原理P3:80C51外部拓展系统





;(写)
MOV P1,#05H
MOV DPTR, #0AAAAH
MOV A, #3FH
MOVX @DPTR, A ;(读)
MOV P1,#02H
MOV DPTR, #0AAAAH
MOVX A, @DPTR
;地址由P0,P1.0~2,P2共同决定



CONT:
MOV DPTR, #0FEFFH ;数据指针指向口地址
MOVX A, @DPTR ;检测按键,向74LS244读入数据
MOVX @DPTR, A ;向74LS273输出数据,驱动LED
SJMP CONT ;循环






MOV DPTR,@7F00H
MOV A,#0C2H ;11000010,(打开了计时器A口为输入(0),B口为输出0,PC1:PC0 = 00(A/B基本输入输出,C口输入))
MOVX @DPTR,A
MOV A,#0AAH
MOV DPTR,#7E25H ;写入的是内存,地址是7E25H,刚好符合写入RAM的要求(81C55的RAM只有256B)
MOVX @DPTR,A

#include <reg51.h> sbit encoder_selet=P2^;
sbit numeric_display=P2^; unsigned char leddata[]={
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E,
0x79, 0x71, 0x76, 0x38, 0x37, 0x3E, 0x73, 0x5C,0x40, 0x00, 0x00
}; unsigned char lower_key_set[]={0x0e,0x0d,0x0b,0x07};
unsigned char lower_key_set_colum[]={0xe0,0xd0,0xb0,0x70}; void delay(unsigned int);
void scan_keyboard(int);
void scan_keyboard_col(int);
void display_key(int); static int pos= ; int main(void)
{
int pos = ;
bstv51_init();
while()
{
scan_keyboard_col();
scan_keyboard_col();
scan_keyboard_col();
scan_keyboard_col();
}
return ;
} void scan_keyboard(int line)
{
unsigned char in, lower_key,in_tmp;
int selet_key; lower_key = lower_key_set[line];
P3 = lower_key|0xf0; in = P3;
in_tmp= in & 0x0f; in &= 0xf0;
in |= lower_key;
if(in!= (lower_key|0xf0))
{
delay();
P3 = lower_key|0xf0;
in = P3;
in &= 0xf0;
in |= lower_key;
if(in != (lower_key|0xf0)) //软件防抖
{
in_tmp = in & 0xf0;
switch(in_tmp) //找到相应的坐标
{
case 0xe0:
selet_key= + line*;
break;
case 0xd0:
selet_key= + line*;
break;
case 0xb0:
selet_key= + line*;
break;
case 0x70:
selet_key= + line*;
break;
}
while(in != (lower_key|0xf0))
{
in = P3;
in &=(lower_key|0xf0);
}
display_key(selet_key);
}
}
} void scan_keyboard_col(int colum)
{
unsigned char in, lower_key,in_tmp;
int selet_key; lower_key = lower_key_set_colum[colum];
P3 = lower_key|0x0f;
in = P3;
in_tmp= in & 0x0f; in &= 0x0f;
in |= lower_key;
if(in!= (lower_key|0x0f))
{
delay();
P3 = lower_key|0x0f;
in = P3;
in &= 0x0f;
in |= lower_key;
if(in != (lower_key|0x0f)) //软件防抖
{
in_tmp = in & 0x0f;
switch(in_tmp) //找到相应的坐标
{
case 0x0e:
selet_key= + colum*;
break;
case 0x0d:
selet_key= + colum*;
break;
case 0x0b:
selet_key= + colum*;
break;
case 0x07:
selet_key= + colum*;
break;
}
while(in != (lower_key|0x0f))
{
in = P3;
in &=(lower_key|0x0f);
}
display_key(selet_key);
}
}
} void display_key(int selet)
{
P0=0x00; //全部点亮
encoder_selet=;
encoder_selet=; P0=leddata[selet];
numeric_display=;
numeric_display=;
} void delay(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>;i--) //i=xms即延时约xms毫秒
for(j=;j>;j--);
}



ORG 0000H
AJMP MAIN_START
ORG 0100H
MAIN_START:
MOV R0,#30H ;设置x数据指针
MOV R1,#50H ;设置y数据指针
MOV R2,# ;清计数器为零
;输出x数据到DAC0832 U2的输入寄存器
GOON:
MOV DPTR,#0DFFFH ;x数据DAC地址为DFFFH
MOV A, @R0
MOVX @DPTR,A ;写数据到DAC0832 U2
INC R0 ;x数据指针指向下一个数据
;输出y数据到DAC0832 U2的输入寄存器
MOV DPTR,#0BFFFH ;y数据DAC地址为BFFFH
MOV A,@R1
MOVX @DPTR,A ;写数据到DAC0832 U3
INC R1 ;y数据指针指向下一个数据
;把所有DAC0832的输入数据寄存器的数据写入到DAC转换寄存器,;1µs后同时输出数据到绘图仪
MOV DPTR,#7FFFH ;DAC转换寄存器地址为7FFFH
MOVX @DPTR,A ;使能和启动D/A转换
INC R2 ;统计输出数据个数
CJNE R2, #,GOON ;输出20个数据后,绘图结束
SJMP $ ;停机
END


A、B、C:模拟通道地址选择信号,A为最低位,C为最高位。
SC:转换开始引脚,正脉冲有效。
EOC:转换结束标志信号,高电平有效,表示转换结束。在与处理器连接时,此引脚可以用来向处理器发出中断,或者是供处理器软件查询。
转换步骤:(直接看代码就好了)
第一步:地址信号到ABC;ALE在ALE的上升沿锁存地址信息,选定通道;
第二步:模拟信号输入到ADC的模拟输入脚,启动SC(一般由80C51的WR脚发出,也就是使用MOVX指令(C51使用xdata的指针),看后面的电压表例子),一定时间内开始转换,转换结束后EOC变高(这个脚一般接80C51的外部中断口)。(注意一般SC和ALE与80C51的WR相连,OE和80C51的RD相连)
第三步:此时可以直接从D0~D7(注意地址要对)拿出数据。(拿出数据时因为有OE的作用所以数据不会变)
3. 单片机与ADC0809的两种连接方法:

;通道1的选择及启动转换
MOV DPTR, #8001H
MOVX @DPTR, A
;此处A的值无关紧要
MOV DPTR, #8000H
MOV A, #01H
MOVX @DPTR,A;此处A的低3位为ADC0809的地址信号
ORG 0000H
LJMP START
ORG 0100H
START:
MOV DPTR, #07FFFH
MOV A,#
MOV R1,# OUTPUT_UP:
MOVX @DPTR,A
ADD A,#
INC R1
NOP
NOP
NOP
NOP
CJNE R1,#,OUTPUT_UP
MOV A,#
MOVX @DPTR,A
LJMP START
END

#include <reg51.h>
#define SUM 4 typedef struct _PanelNumber
{
unsigned char digitalNum;
unsigned char port;
}PanelNumber; void delay(void); int main(void)
{
PanelNumber numberSet[SUM]={{0xF9,0x70}, //num:1 port:P2^7
{0xA4,0xb0}, //num:2 port:P2^6
{0xB0,0xd0}, //num:3 port:P2^5
{0x99,0xe0}}; //num:4 port:P2^4
int i;
while()
{
for(i = ;i!=SUM;i++)
{
P2 = 0xff;
P2 = numberSet[i].port;
P0 = numberSet[i].digitalNum;
delay();
}
}
return ;
} void delay(void)
{
unsigned char i,j;
for (i=;i<;i++)
{
for (j=;j<;j++);
}
}
#include <reg51.h>
#include "voltmeter.h" static NumberPanel numberPanel[]; int main(void)
{
IT0 = ;//failling edge trigger
EX0 = ;//enable interrupt 0
EA = ;//enable global interrupt numberPanel[].outputPort = 0xfbff;
numberPanel[].outputPort = 0xfdff;
numberPanel[].outputPort = 0xfeff; START_ADC(adcAddress);//start adc transformation while();
return ;
} void OnADCTransform_Completed()
interrupt INT0 using REGISTER_0
{
unsigned char result = ;
float rResult; READ_DATA(result,adcAddress); rResult = (float)result * 0.0196078;
rResult *= ; translateResult((int)(rResult)); START_ADC(adcAddress);//restart adc transformation
} void translateResult(int result)
{
int dividend = ,i = ;
unsigned char number; for(;dividend != ; dividend /= , i--)
{
number = digitalNumberSet[result/ dividend];
result %= dividend; //open WD and output the data,
//the data will lock in the register while WD is low level
OUTPUT_DATA(i,number);
}
}
#define INT0 0
#define REGISTER_0 0
#define START_ADC(a) ((*a) = 0)
#define OUTPUT_DATA(i,data) ((*(numberPanel[i].outputPort)) = data)
#define READ_DATA(data,add) (data = (*add)) //choose channel 0, while P2.7 is low level
unsigned char xdata *const adcAddress = 0x0ff8; typedef struct _NumberPanel
{
unsigned char xdata *outputPort;
}NumberPanel; unsigned char const digitalNumberSet[]
= {0xC0, 0xF9, 0xA4, 0xB0,
0x99, 0x92, 0x82, 0xF8,
0x00, 0x90, 0x88, 0x83,
0xC6, 0xA1, 0x86, 0x8E}; void translateResult(unsigned char result);
单片微机原理P3:80C51外部拓展系统的更多相关文章
- 单片微机原理P0:80C51结构原理
本来我真的不想让51的东西出现在我的博客上的,因为51这种东西真的太low了,学了最多就所谓的垃圾科创利用一下,但是想一下这门课我也要考试,还是写一点东西顺便放博客上吧. 这一系列主要参考<单片 ...
- 单片微机原理P1:80C51指令系统和编程方法
0. 寻址方式 寻址方式在汇编中是很重要的,汇编所有的操作都是和和内存或者寄存器打交道的,在80C51里面一共7种寻址方式. 1. 立即寻址: 这个没什么好说的,就是往寄存器或者内存里面写立即数, ...
- 单片微机原理P2:80C51外部中断与定时器系统
0. 外部中断 书上的废话当然是很多的了,对于中断我想大家应该早就有一个很直观的认识,就是"设置断点,执行外部外码,然后返回断点"这样的三个过程.中断给系统提供了一个良好的响应模式 ...
- 单片微机原理P4:80C51串口与串行总线拓展
0. 串口通讯 0. 串口通讯的数据传输方式:单工(单向传输数据),半双工(非同时双向传输),全双工(同时,双向传输) 1. 根据通信方式的不同又分为同步通讯和异步通讯. 同步通讯:所有设备都使用同一 ...
- 80x86/Pentium微机原理及接口技术-微处理器-学习笔记
80x86/ Pentium微机原理及接口技术 1. 计算机基础... 1 1.1常用术语... 1 1.2计算机中数与编码的表示方法... 1 1.2.1进制表示及进制转换... 1 1.2 ...
- html基本标签表单实现交互原理,单选框,复选框,下拉框介绍
表单是什么?表单是前端和服务器做交互的一种机制,表单收集用户输入信息,之后发送或者提交给服务器.用户在输入的信息称之为内容,内容的文本分为普通和密码型,用户通过单选框.复选框.下拉框(也就是下拉菜单) ...
- AJAX练习(一):制作可以自动校验的表单(从原理上分析ajax的作用)
继上文(AJAX(一)AJAX的简介和基础)作为联系. 传统网页在注册时检测用户名是否被占用,传统的校验显然缓慢笨拙. 当ajax出现后,这种体验有了很大的改观,因为在用户填写表单时,签名的表单项已经 ...
- 微机原理基础(四)—— MSC51
一.MCS51基本组成(STC89C52) CPU(8051CPU) + 存储器(4KB ROM/256B RAM)+外设(4组IO口,两个定时器,一个串口) 1.组成结构简图 ...
- Spring的单例实现原理-登记式单例
单例模式有饿汉模式.懒汉模式.静态内部类.枚举等方式实现,但由于以上模式的构造方法是私有的,不可继承,Spring为实现单例类可继承,使用的是单例注册表的方式(登记式单例). 什么是单例注册表呢, 登 ...
随机推荐
- RF学习过程中遇到的问题
1.写了一个打开浏览器的用例,执行用例时报需要对应的浏览器驱动,此时应下载对应的浏览器驱动,把该执行文件放到python的安装根目录下,再执行用例就成功了 2.日志不见的问题:需要杀进程
- 关于栈和堆的定量分析(★firecat推荐★)
文章来源:http://blog.csdn.net/bigbug_zju/article/details/39525281 计算机系统中的堆和栈是跟程序员最密切的两个概念.如果没有栈和堆的概念,下面程 ...
- zabbix如何选择适合的监控类型(107)
zabbix agent zabbix自带的客户端程序(被动模式),zabbix server主动向它收集监控数据.agent提供丰富的key,包括不限于cpu.内存.网络.磁盘.web等等.如果你不 ...
- BZOJ1680: [Usaco2005 Mar]Yogurt factory
1680: [Usaco2005 Mar]Yogurt factory Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 106 Solved: 74[Su ...
- CSS中display:block的使用介绍
在CSS的规定中,每个页面元素都有一个display的属性,用于确定这个元素的类型是行内元素,还是块级元素: (1)行内元素:元素在一行内水平排列,依附于其他块级元素存在,因此,对行内元素设置高度.宽 ...
- 动态规划——min/max的单调性优化总结
一般形式: $max\{min(ax+by+c,dF(x)+eG(y)+f)\},其中F(x)和G(y)是单调函数.$ 或 $min\{max(ax+by+c,dF(x)+eG(y)+f)\},其中F ...
- bzoj1178
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1178 看ppt http://wenku.baidu.com/link?url=dJv6LNm ...
- HDU 3586 : Information Disturbing
Problem Description In the battlefield , an effective way to defeat enemies is to break their commun ...
- 站点建设10个最好的响应的HTML5滑块插件
大多数的最佳响应的HTML5滑块插件能够使用移动应用程序,站点建设项目,以及Web开发项目提供一些令人兴奋的功能,如无限的动画效果,百分之中的一个百响应布局设计和很多其它. 1.别急!慢慢来 功能丰富 ...
- 辛星解读mysql的用户管理
可能做开发的多半不太关注这方面,可是要说到做运维.那就不能不关注了.由于我们都知道,root的权限太大了.不是随便能用的.我们平时最好用一些比較低的权限的用户.这样会让我们的安全性大大提高,也能防止我 ...