Keil C51对同一端口的连续读取方法
C语言是当前举世公认的高效简洁而又非常贴近硬件的编程语言之一。将C语言向单片机MCS-51上的移植始于2O世纪8O年代的中后期,经过近1O年的发展,C语言克服了产生代码过长、运行速度较慢的缺点,并且由于C语言在开发速度、软件质量、结构化、可维护性等方面有着汇编语言无法比拟的优势,从而得到日益广泛的应用。Keil C51是德国Keil公司开发的单片机C语言编译系统.该软件功能完备,是目前国内技术开发人员使用最为广泛的语言之一。
在实际工作中发现,用C语言编写的对同一端口进行连续读取的程序,经Keil C51编译后执行结果往往会出错,现以8051单片机读取12位A/D MAX197为例,如图1所示。
图1中,P1.1口用于读取转换完成时A/D发出的中断信号,P1.0对读取高4位或低8位进行选择。现假定A/D 的地址为8000H,启动CH0端口工作字为40H。为得到相应的高、低位转换数据,用C语言编程如下。
#include<reg51.h>
unsigned char xdata MAX197 _at_ 0x8000;
sbit MAXINT= P1^1;
sbit MAXHBEN= P1^0;
……
void main()
{unsigned char up4,down8;//设置接收数据的2个变量
……
MAX197= 0X40;//启动A/D CH0口进行转换
while(MAXINT) //等待转换完成
{};
P1.0=0; //读取低8位
down8=MAX197;
P1.0=1; //读取高4位
up4=MAX197;
}
上述的程序并没有如所希望的那样分别得到高、低位数据,实际上在down8和up4中得到的都是低8位的数据。下面是上段C语言经编译后的部分代码。
41: //取低8位
42: MAXHBEN=0;
C:0x000C C290 CLR MAXHBEN(0x90.0)
43: down8=MAX197;
C:0x000E 908000 MOV DPTR,#MAX197(0x8000)
C:0x0011 E0 MOVX A,@DPTR
C:0x0012 F509 MOV 0x09,A
44: //取高4位
45: MAXHBEN=1
C:0x0014 D290 SETB MAXHBEN(0x90.0)
46: up4=MAX197;
47:
48:
C:0x0016 F5O8 MOV 0x08,A //0x08为up4
49: }
通过分析上面的程序会发现,C编译出来的程序并没有在P1.0置为高电位后再去读一次端口,而只是直接将上次读来的结果直接送给高4位变量。如果先读高位后读低位,结果会得到两个高4位数据。为证实这一点,将4条连续重复读取一个外部端口的C语言语句放在一起,编译后发现只有第一条语句被编译执行。也就是说,Keil C51对于连续重复读取同一个端口地址,在编译时进行了“特殊”处理,这一点是十分值得注意的。那么对于确实需要对同一端口进行连续读取的情况应该如何处理呢?下面介绍两种方法以供参考。
第一种方法:加延时。
延时不宜太长,特别是在对转换速度要求较高时。首先写一个延时函数:
void delay()
{unsigned char i;
for (i=0,i<=1;i++);
}
然后将延时程序放在上面两次读取的中间位置。
P1.0=0; //读取低8位
down8=MAX197:
delay();
P1.0=1; //读取高4位
up4=MAX197;
编译后的结果如下:
49: //取低8位
50: MAXHBEN=0:
C:0x000C C29O CLR MAXHBEN(0x90.0)
51: down8=MAX197;
C:0x000E 908000 MOV DPTR,#MAX197(0x8000)
C:0x0011 E0 MOVX A,@DPTR
C:0x0012 F509 MOV 0x09,A
52: delay();
53: //取高4位
C:0x0014 120029 LCALL delay(C:0029)
54: MAXHBEN = 1;
C:0x0017 D290 SETB MAXHBEN(0x90.0)
55:up4=MAX197;
56:
57:
C:0x0019 E0 MOVX A,@DPTR
C:0x001A F508 MOV 0x08,A
58: }
可以看出,在将P1.0置高后,又对端口进行了一次读写,程序正常并得到了高4位。
第二种方法:另设指针。
void main()
{unsigned char up4,down8; //设置接收数据的2个变量
unsinged char xdata *pt1;
pt1=0x8000;
……
MAX197=0X40; //启动A/D CH0口进行转换
while(MAXINT) //等待转换完成
{};
P1.0=0; //读取低8位
down8= MAX197:
P1.0=1; //读取高4位
up4=*pt1:
……
编译的结果如下:
42: //取低8位
43: MAXHBEN=0;
C:0x0010 C290 CLR MAXHBEN(0x90.0)
44: down8=MAX197;
C:0x0012 908000 MOV DPTR,#MAX197(0x8000)
C:0x0015 E0 M0VX A,@DPTR
C:0x0016 F509 MOV 0x09,A
45: MAXHBEN=1:
46: //取高4位
47:
C:0x0018 D290 SETB MAXHBEN(0x90.0)
48: up4=*pt1:
49:
50:
C:0x001A 8F82 MOV DPL(0x82),R7
C:0x001C 8E83 MOV DPH (0x83),R6
C:0x001E E0 MOVX A,@DPTR
C:0x001F F508 MOV 0x08,A
上述两种方法都很好地解决了Keil C51中不能处理对一个端口进行连续读写的问题,但如果对转换速度要求特别高,建议最好使用第二种方法。
《 Keil C51总线外设操作问题的深入分析》对本文问题做了更深入的剖析。
Keil C51对同一端口的连续读取方法的更多相关文章
- Keil C51程序设计中几种精确延时方法
1 使用定时器/计数器实现精确延时 单片机系统一般常选用11.059 2 MHz.12 MHz或6 MHz晶振.第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确 ...
- Keil C51里面lib文件生成和调用方法
一.包含关系 LCD1602.C里面包含LCD1602.H LCD1602.H的文件格式 二.设置生成lib文件 三.Lib文件调用 添加lib文件对话框 添加后的lib文件 呵呵^_^,这样就可以删 ...
- Keil C51总线外设操作问题的深入分析
阅读了<单片机与嵌入式系统应用>2005年第10期杂志<经验交流>栏目的一篇文章<Keil C51对同一端口的连续读取方法>(原文)后,笔者认为该文并未就此问题进行 ...
- KEIL C51代码优化详细分析
阅读了<单片机与嵌入式系统应用>2005年第10期杂志<经验交流>栏目的一篇文章<Keil C51对同一端口的连续读取方法>(原文)后,笔者认为该文并未就此问题进行 ...
- keil c51笔记
第一章 Keil C51开发系统基本知识 第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性. ...
- Keil C51程序调试过程
用Keil C51编写程序时,经常需要调试,如果不是经常用这个软件的话,很容易忘记这些调试步骤,现在举一个例子“验证延迟函数delay()使其延迟的时间为500ms”说明. 源程序写完后,就可以调试了 ...
- KEIL C51高级编程
第一节 绝对地址访问C51提供了三种访问绝对地址的方法: 1. 绝对宏:在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括:CBYTE.XBYTE.PWORD.DBYTE.CWO ...
- Keil C51中变量的使用
引言 8051内核单片机是一种通用单片机,在国内占有较大的市场份额.在将C语言用于51内核单片机的研究方面,Keil公司做得最为成功.由于51内核单片机的存储结构的特殊性,Keil C51中变量的使用 ...
- Keil C51 知识点
第一节 Keil C51扩展关键字 深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型 ...
随机推荐
- Android批量图片载入经典系列——使用LruCache、AsyncTask缓存并异步载入图片
一.问题描写叙述 使用LruCache.AsyncTask实现批量图片的载入并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)载入图片,并放入缓存中 2.及时 ...
- PHP函数的默认参数
<?php /** * 函数的参数个数任意 */function foo() { $args = func_get_args(); static $i = 0; //统计参数个数 /* fore ...
- 让jquery easyui datagrid列支持绑定嵌套对象
嵌套对象是指返回的json数据,是对象的某个属性自带有属性.而我们恰恰又需要这个属性,默认情况下easyui的datagrid是不支持绑定嵌套对象的.比如:datagrid的field属性只能为fie ...
- poj 3349 (最小表示法)
开始按hash做的 交上去就wa 但是和标称拍了半天也没有不一样的 可能是生成的数据太水了吧... #include<iostream> #include<cstdio> #i ...
- 学习日记-----ORM
ORM ORM(Object Relation Mapping)对象关系映射 实质:将数据库中 的业务数据用对象的形式表现出来,使用ORM在业务逻辑层和数据访问层之间充当桥梁 核心原则: 简单性 传达 ...
- 怎样成为PHP 方向的一个合格的架构师
突然看到这篇文章, 值得反省, 乐在其中, 在接下来的发展中不被淘汰的都来看看, 如何成为一个架构师先明确这里所指的PHP工程师,是指主要以PHP进行Web系统的开发,没有使用其的语言工作过.工作经验 ...
- PHP语言中使用JSON
原文地址:http://www.ruanyifeng.com/blog/2011/01/json_in_php.html 在PHP语言中使用JSON 目前,JSON已经成为最流行的数据交换格式之一,各 ...
- c - 给分数分级别
/* 题目: 学习成绩>=90 分的同学用 A 表示, 80-89 分之间的用 B 表示,70-79 分的用 C 表示, 60-69 分用 D表示,小于60分用E表示. 分析: 使用swith. ...
- mac更新之前,好容易把网络设置好
1.[虚拟机]虚拟网络编辑器--恢复默认设置 [主机网络]自动ip [VM8] 当时忘记将mac里面的网络设置截图...导致更新后网络出问题后却显示网络设置失败
- LINQ对List列表随机排序,取N条数据
List<Art_Search> artList=new List<Art_Search>(); artList=artList.OrderBy(s => Guid.Ne ...