单片机数据记录

2016-11-20 19:02:56 xlhcgd 阅读数 2715

51之51单片机RAM数据存储区学习笔记


转自:http://www.eeworld.com.cn/mcu/2014/0826/article_16044.html




1.RAM keil C语言编程

RAM是程序运行中存放随机变量的数据空间。在keil中编写程序,如果当前模式为small模式,如果总的变量大小未超过128B,则未初始化的变量的初值默认为0.如果所有的变量超过单片机small模式下的128B大小,则必须对变量进行初始化,否则超过RAM大小变量的值是不确定的,在small模式下超过128B大小的变量也必须在编译器中重新设定存储器的存储模式。

在keil中,可选择small,compact,large三种方式存储数据变量:


在keil中可以用“Target Options”来配置这一项:


2.片内数据存储区

(1) 工作寄存器区

工作寄存器区位于片内数据存储器中的00H~1FH单元,共32字节( 如此说来每个单元是一个字节了 ),分成四组。每组8个字节,分别记为R0~R7.


程序默认在0区工作寄存器组存放中间运算数据。等待中断来时,中断数据工作寄存器组由0区切换到其它区域。

选择四组工作寄存器区的哪一组作为R0~R7由位于PSW寄存器的两位RS1,RS0来确定.

RS1,RS0称为区开关或组开关,两位就可决定四种状态.


2)位寻址区

用户存储区位于片内数据存储器中的020H~02FH单元,共16个字节,共128位,每个字节单元的位都有一个单独的地址,分别为00H-07H,如020H.1表示020H单元的bit[1]位。020H~02FH单元可作为位寻址区。这个范围内的存储单元最大的用处就是能进行位操作,在C语言中,只能用位操作运算符(&、|、^、~、<<、>>)来对字节数据进行位操作运算。如果用汇编指令就可以直接对此片存储单片进行位操作。

如 SETB, 020H.1 就将020H的bit[1]置为了1.

除了RAM此片能进行位寻址的用户存储区以外,还有一些特殊的功能寄存器( SFR )也能进行位寻址。

(3)数据缓冲区

51系列数据缓冲区地址为30H-7FH,共80字节。只能字节寻址,不能位寻址。由于工作寄存器和位寻址区,数据缓冲区是统一编址的,所以这三者都可以用作数据缓冲区。

(4)堆,栈

栈:由系统自动分配释放,存局部值。

堆:一般由程序员分配和释放(在C中用malloc/free操作)。

栈指针SP:8位寄存器,栈最大可达128单元,只可在片内RAM中进行栈操作。

栈作用:用来保存地址、数据信息、具有先进后出特性,也是一种能存放二进制数据的空间。

MC51栈采用满顶法向上生成的软件堆栈。

软件栈:借助SP进行控制操作。

栈向上生长:新压栈的数据成为栈顶。

栈向下生长:新压入的数据远离栈顶。

地址大小还得看存储方式。

(5)专用寄存器区

专用寄存器区,也称特殊功能寄存器区 SFR

SPECIAL FUNCTIONREGISTER

寻址地址离散地分布在80H~FFH,共128字节的空间.而实际有用的只有21个字节,即在这一空间里只有18个专用功能寄存器,其中有3个专用功能寄存器占用了两个字节.SFR主要用于片内硬件的管理,通常只能以字节为单位借助于MOV指令直接寻址,但也有一些专用功能寄存器可以位寻址。

包含程序状态字PSW、数据指针寄存器DPTR、端口地址P0-P0、其它专用寄存器(累加器A、B)

3.片外数据存储区

片外RAM区:可寻空间为共64K 0000H~FFFFH,

总是使用MOVX类指令寻址

借助于工作寄存器R0或R1间接寻址时,可寻256字节

从片外RAM区取数据: MOVX A,@Ri i=0-1

向片外RAM区存数据: MOVX @Ri,A

借助16位的数据指针DPTR间接寻址,可寻64K字节:

从片外RAM区取数据: MOVX A,@DPTR

向片外RAM区存数据: MOVX @DPTR,A

<此段摘抄,防后会使用>

区分是访问内部存储器还是外部存储器地址靠指令来区分。

这里,片内的存储区即常念叨的“寄存器”,片外的ram存储区即指“系统内存”。





2018-08-04 09:42:47 bolinste 阅读数 1656

尊重原创,转载请说明出处……

 

在工作中用单片机很久了,对通信数据的处理有一些小小的心得体会。分享出来供讨论和指正。

以下讨论基于C语言。

 

在单片机中串口是一个很重要和基本的外设。对串口数据的存储很多大拿都有自己的方式方法。个人总结有如下几种:

1、开辟一个较大的数组对数据进行保存。有时会结合定时器进行数据的“分帧”/“分包”

2、使用链表的方式进行数据存储。每个字节做成一个节点,逐节增加节点予以记录。

3、使用内存管理的方式。有经验的工程师会自己写内存管理的程序,把串口读到的数据通过内存管理进行处理。

4、使用OS的数据队列。

 

几种方式的对比分析:

编号 优点 缺点
1 写法简单,容易理解 数组长度有限,有数据溢出的风险。
2 理论实现容易,数组长度灵活 占用的内存过大
3 灵活易用,数组长度灵活,不依赖操作系统 理解起来可能会有难度
4 灵活易用,数组长度灵活,依赖操作系统 必须依赖OS

 

 

 

 

 

 

下面对上述的几种方式做详细的介绍。

 

 

2020-03-23 21:00:04 Sunmoon98 阅读数 82

本文将以51单片机的I2C通信协议为例,将涉及到I2C的基本过程以及其中我认为比较重要的点。

  1. I2C的基本过程

首先:IIC作为一种串行通信协议,它需要两根线来完成数据传输。一根是时钟线SCL,另外一根是数据传输线SDA,其中这个数据传输线是双向的,既可以主机向从机也可以从机向主机。

发送过程:发送一个开始信号(SCL为高电平SDA由高电平变成低电平,持续时间大于4.7us。为了方便统一将延时设置为10us)。紧随着是7位从机地址位,而这7位地址位前四位为固定地址,后三位为可编程地址。一般情况下,固定地址为1010(十六进制的a)。从机地址位之后的一位是传输方向位,0表示主机向从机放松数据。然后,从机要向主机发送一个应答。表示被寻址的从机知道自己需要接收地址。发送应答后,开始发送数据,每发送一个字节的数据,都需要进行应答或着非应答来进行判断。(这是主机向从机发送数据)

代码部分:

unsigned char I2cSendByte(unsigned char dat)
{
	unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。		
	for(a=0;a<8;a++)//要发送8位,从最高位开始
	{
		SDA=dat>>7;	 //起始信号之后SCL=0,所以可以直接改变SDA信号
		dat=dat<<1;
		Delay10us();
		SCL=1;
		Delay10us();//建立时间>4.7us
		SCL=0;		//低电平进行传送数据
		Delay10us();//时间大于4us		
	}
	SDA=1;	 //释放时钟线和数据线
	Delay10us(); //也可以不写
	SCL=1;
	while(SDA)//等待应答,也就是等待从设备把SDA拉低
	{
		b++;
		if(b>200)	 //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
		{
			SCL=0;
			Delay10us();
			return 0;
		}
	}
	SCL=0;
	Delay10us();
 	return 1;		
}

这个部分用来将我们写入的命令转换成数据线相应的高低电平起伏。简单的说,就是发送数据。
需要注意的是,我们需要先将高位数据发送,这个过程我们可以通过右移7位来实现;(SDA=dat>>7)是为了获取最高位的数据(0或1)。dat=dat<<1;是为下一次循环获取第二高位数据做准备。至于后面的while循环部分,是为了判断是否产生应答,以决定是否继续发送数据。以下是时序图用来增加理解:在这里插入图片描述
接下来是读取数据部分:

unsigned char I2cReadByte()
{
	unsigned char a=0,dat=0;
	SDA=1;			//起始和发送一个字节之后SCL都是0
	Delay10us();
	for(a=0;a<8;a++)//接收8个字节
	{
		SCL=1;
		Delay10us(); //使数据保持稳定  
		dat<<=1;
		dat|=SDA;	   
		Delay10us();
		SCL=0;
		Delay10us();
	}
	return dat;		
}

这里有一个比较重要的点:dat=0,当dat<<=1之后,它依旧是0,但是当我们进行dat|=SDA运算后,dat为0000 0001(在这里,我假设sda为高电平),如果我们需要纠结dat为0的时候是几位的,在这里,我理解为8位,毕竟我以前都误以为是一位…因为当它是一位,会导致整个循环过后,数据是9位…
除此之外,还需要注意一个顺序问题!先左移,在进行与运算!!!在这里,我简单写一个循环过程(假设sda一直为高电平):dat=0-----> dat<<1(dat=0000 0000)----->dat|=SDA(dat= 0000 0001)-----> dat<<1(dat=0000 0010)----->dat|=SDA(dat=0000 0011);到此,我想要强调的是,这个顺序可以保证移位8次,如果顺序相反,会导致移位9次,当然了,没有必要去记忆背诵这个顺序,理解才是最重要的。

至此,我想要记录的主要内容已经over了~

对了!如果从机在接收完一次数据后不希望继续接收,需要在以此刻为基准,接收的第一个数据后发送一个非应答信号!千万不要记错了

2008-01-17 16:02:00 mybirdsky 阅读数 489
[转贴 2006-05-06 00:09:07

字体变小 字体变大
[单片机]用单片机数据采集系统研究瞬变过程
小伟 发表于 2006-4-30 22:24:00
摘 要:介绍用单片机数据采集系统研究RC电路的瞬变过程,并利用显示器显示其变化情况。非常直观地展示了RC电路的过渡过程,在科学实验的应用中取得了很好的效果。
关键词:过渡过程 ADC0809芯片 DAC0832芯片

0 引 言
在教学实验及科学实验中,我们常常需要了解充电的电压、电流曲线、放电的电压曲线,记录并整理数据,画曲线,这里使用单片机数据采集系统可以直观了解RC电路的过渡过程,用数据采集系统得出的数据计算该RC电路的时间常数。
1 RC电路的过渡过程
实验电路如图1所示。


当数据采集系统启动后,U1为高电平,晶体三极管T1导通,T1集电极UC1下降,合二极管D截止,三极管T2也截止,而电容器C通过r4及r5充电,充电时间常数近似为
   τ充=(r4+r5)·C
电阻r5上的电压Ur与电容电流成正比,UC近似为电容器电压,将UC与Ur送入数据采集系统,可以得到256对电容电压及电容电流的数据。接着再启动数据采集系统,U1为低电平,T1截止,+5V电源通过r1及D使T2的基极,发射极间有正向电流,因而T2导通 。这时C通过r3、r5、T2放电,放电时间常数近似为
τ放=(r5+r3)·C
在数据采集系统启动后,给出UC有256个数据,由于放电时间常数小,因此UC很快到零 ,由于ic只有负值,读不出来,显示为零。
2 工作原理
2.1 硬件电路的设计
本系统的硬件电路可选择8031单片机为主控制器,加上地址锁存器373,程序存储器2764和数据存隼器6116,构成一个单片机最小系统。在单片机最小系统上扩展ADC0809芯片,DAC0832芯片,构成一个完整的数据采集系统。
数据采集系统的框图如图2所示。

2.2 软件设计
当单片机控制电路时,A/D变换器立即工作,单片机分时对模拟输入信号进行采集,输入的模拟量变换为数字量后存入单片机存储器RAM中,然后,单片机将 RAM中的数字量送入D/A转换电路,D/A电路通常输出与数字量相对应的模拟电流,经I/V变换成模拟电压值。得到的模拟电压与输入模拟信号一致,可用示波器观察其过渡过程的变化 。程序流程框图如图3所示。

3 结束语
本系统可直接从示波器上读取充电电压、电流曲线,放电的电压曲线,记录并整理数据,由充电曲线上画曲线的切线,可求充电时间常数。由放电曲线上画曲线的切线可求放电时间常数。用数据采集系统研究的瞬变过程,方便、直观,加深对RC电路过渡过程的了解。



   参考文献



1 孙育才编.MCS-51系列单片微型计算机及其应用.南京:东南大学出版社,1998
2 王秀珍编.微型计算机A/D、D/A转换接口技术及数据采集系统.北京:清华大学出版社,1984
2019-01-09 00:53:34 anny0884 阅读数 277

51单片机数据区详解


从数据存储类型来说,8051系列有片内、片外程序存储器,片内程序存储器还分直接寻址区和间接寻址类型,以及根据51系列特点而设定的pdata类型。使用不同的存储器,将使程序的执行效率不同,在编写C51程序时,最好指定变量的存储类型,这样将有利于提高程序执行效率。与ANSI-C稍有不同,它只分SAMLL、COMPACT、LARGE模式,各种不同的模式对应不同的实际硬件系统,也将有不同的编译结果。

在51系列中data,idata,xdata,pdata的区别:

data: 固定指前面0x00~0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小。

idata: 固定指前面0x00~0xff的256个RAM,其中前128个RAM和data的128个RAM完全相同,只是因为访问的方式不同。idata是用类似C中的指针方式访问的。汇编中的语句为:mox ACC,@Rx.(不重要的补充:Cidata做指针式的访问效果很好)

xdata:外部扩展RAM,一般指外部0x0000~0xffff空间,用DPTR访问。

pdata:外部扩展RAM的低256个字节,地址出现在A0-A7上时读写,用movx ACC,@Rx读写。这个比较特殊,而且C51好像对此有BUG,建议少用。(这是2014年的记录,不知以后是否有改进)

单片机C语言中unsigned char code table[] code是什么作用?

code的作用是高速单片机,我定义的数据要放在ROM(程序存储区)里面,写入后就不能再更改。因为C语言中没办法详细描述存入的是ROM还是RAM,所以在软件中添加了这一个语句代替汇编指令的作用,对应的还有data是存入RAM的意思。

程序可以简单的分为code(程序)和data(数据)区,code区在运行的时候是不可以随便更改的,data区放全局变量和临时变量,是要不断的改变的,cpu从code区读取指令,对data区的数据进行运算处理,因此code区存储在什么介质上并不重要,像以前的计算机程序存储在卡片上,code区也可以放在rom里面,也可以放在 RAM里面,也可以放在flash里面(但是运行速度要慢很多,主要是读flash比读RAM要费时间), 因此一般的做法是将程序放在flash里面,然后load到RAM里面运行的,放到rom里面改动不了。

bdata 如何使用呢?
若程序需要8个或者更多的bit变量,如果你想一次性给8个变量赋值的话就不方便了,又不可以定义bit数组,只有一个方法。

    char bdata MODE;
     sbit MODE_7 = MODE^7;
     sbit MODE_6 = MODE^6;
     sbit MODE_5 = MODE^5;
     sbit MODE_4 = MODE^4;
     sbit MODE_3 = MODE^3;
     sbit MODE_2 = MODE^2;
     sbit MODE_1 = MODE^1;
     sbit MODE_0 = MODE^0;

8个bit变量MODE_n就定义好了。这是定义语句,Keil C的特殊数据类型。记住一定要sbit而不能用bit MODE_0 =MODE^0;赋值语句要是这么写C语言就视为异或运算。

keil生成的文件 注释
.plg 编译器编译结果
.hex和.bin 可执行文件
.map和.lst 链接文件
.o 目标文件
.crf 、.Inp、.d和.axf 调试文件
.opt 保存工程配置信息
.bak 工程备份文件
M51文件 startup文件。

普通51系列单片机存储空间资源分布情况:

空间名 地址范围 说明
DATA D:00H~7FH 片内RAM直接寻址区
BDATA D:20H~2FH 片内RAM位寻址区
IDATA I:00H~FFH 片内RAM间接寻址区
XDATA X:0000H~FFFFH 64K片外RAM数据区
CODE C:0000H~FFFFH 64K片内外ROM代码区
BANK0~31 B0~B31:0000H ~ FFFFH 分组代码区,最大可扩展32X64K ROM
HDATA (新) X:0000H~FFFFFFH 16M扩展片外ROM数据区
hconst(新ECODE) C:0000H~FFFFFFH 16M扩展片外ROM常数区(对dallas390可用作代码区)