PIC单片机如何从汇编转向PICC.doc

上传人:白大夫 文档编号:3270705 上传时间:2019-08-07 格式:DOC 页数:9 大小:36KB
返回 下载 相关 举报
PIC单片机如何从汇编转向PICC.doc_第1页
第1页 / 共9页
亲,该文档总共9页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《PIC单片机如何从汇编转向PICC.doc》由会员分享,可在线阅读,更多相关《PIC单片机如何从汇编转向PICC.doc(9页珍藏版)》请在三一文库上搜索。

1、PIC单片机如何从汇编转向PICC一、如何从汇编转向PICC首先要求你要有C语言的基础。C代码的头文件一定要有include,它是很多头文件的集合,C编译器在pic.h 中根据你的芯片自动载入相应的其它头文件。这点比汇编好用。载入的头文件中其实是声明芯片的寄存器和一些函数。static volaTIle unsigned char TMR0 0x01;staTIc volaTIle unsigned char PCL 0x02;staTIc volatile unsigned char STATUS 0x03;可以看出和汇编的头文件中定义寄存器是差不多的。如下:TMR0 EQU 0X01;PC

2、L EQU 0X02;STATUS EQU 0X03;都是把无聊的地址定义为大家公认的名字。1、如何赋值?如对TMR0 附值,汇编中:MOVLW 200;MOVWF TMR0;当然得保证当前页面在0,不然会出错。C语言:TMR0=200;/无论在任何页面都不会出错。可以看出来C是很直接了当的。并且最大好处是操作一个寄存器时候,不用考虑页面的问题。一切由C自动完成。2、如何位操作?汇编中的位操作是很容易的。在C中更简单。C的头文件中已经对所有可能需要位操作的寄存器的每一位都有定义名称:如:PORTA 的每一个I/O口定义为:RA0、RA1、RA2。RA7。OPTION 的每一位定义为:PS0、P

3、S1、PS2 、PSA 、T0SE、T0CS、INTEDG 、RBPU。可以对其直接进行运算和附值。如:RA0=0;RA2=1;在汇编中是:BCF PORTA,0;BSF PORTA,2;可以看出2 者是大同小异的,只是C 中不需要考虑页面的问题。3、内存分配问题在汇编中定义一个内存是一件很小心的问题,要考虑太多的问题,稍微不注意就会出错。比如16 位的运算等。用C 就不需要考虑太多。下面给个例子:16 位的除法(C 代码):INT X=5000;INT Y=1000;INT Z=X/Y;而在汇编中则需要花太多精力。给一个小的C 代码,用RA0 控制一个LED 闪烁:includevoid m

4、ain()int x;CMCON=0B111; /掉A 口比较器,要是有比较器功能的话。ADCON1=0B110; /掉A/D 功能,要是有A/D 功能的话。TRISA=0; /RA 口全为输出。loop:RA0=!RA0;for(x=60000;-x;); /延时goto loop;说说RA0=!RA0 的意思:PIC 对PORT 寄存器操作都是先读取-修改-写入。上句的含义是程序先读RA0,然后取反,最后把运算后的值重新写入RA0,这就实现了闪烁的功能。二、浅谈PICC 的位操作由于PIC 处理器对位操作是最高效的,所以把一些BOOL 变量放在一个内存的位中,既可以达到运算速度快,又可以达

5、到最大限度节省空间的目的。在C 中的位操作有多种选择。*如:char x;x=x|0B00001000;char x;x=x 把上面的变成公式则是:#define bitset(var,bitno)(var |=1#define bitclr(var,bitno)(var char x;bitset(x,4);char x;bitclr (x,5);*但上述的方法有缺点,就是对每一位的含义不直观,最好是能在代码中能直观看出每一位代表的意思,这样就能提高编程效率,避免出错。如果我们想用X 的0-2 位分别表示温度、电压、电流的BOOL 值可以如下:unsigned char x 0x20;bit

6、 temperature (unsigned)bit voltage (unsigned)bit current (unsigned)这样定义后X的位就有一个形象化的名字,不再是枯燥的1、2、3、4 等数字了。可以对X 全局修改,也可以对每一位进行操作:char=255;temperature=0;if(voltage)。.。.*还有一个方法是用C 的struct 结构来定义,如:struct cypoktemperature:1;voltage:1;current:1;none:4;x 0x20;这样就可以用x.temperature=0;if(x.current)。.。等操作了。*上面的方

7、法在一些简单的设计中很有效,但对于复杂的设计中就比较吃力。如象在多路工业控制上。前端需要分别收集多路的多路信号,然后再设定控制多路的多路输出。如:有2 路控制,每一路的前端信号有温度、电压、电流。后端控制有电机、喇叭、继电器、LED。如果用汇编来实现的话,是很头疼的事情,用C 来实现是很轻松的事情,这里也涉及到一点C 的内存管理(其实C 的最大优点就是内存管理)。采用如下结构:union cypokstruct outmotor:1;relay:1;speaker:1;led1:1;led2:1;out;struct innone:5;temperature:1;voltage:1;curre

8、nt:1;in;char x;union cypok an1;union cypok an2;上面的结构有什么好处呢?细分了信号的路an1 和an2;细分了每一路的信号的类型(是前端信号in 还是后端信号out):an1.in ;an1.out;an2.in;an2.out;然后又细分了每一路信号的具体含义,如:an1.in.temperature;an1.out.motor;an2.in.voltage;an2.out.led2;等这样的结构很直观的在2 个内存中就表示了2 路信号。并且可以极其方便的扩充。如添加更多路的信号,只需要添加:union cypok an3;union cypok

9、 an4;从上面就可以看出用C 的巨大好处。三、PICC 之延时函数和循环体优化。很多朋友说C 中不能精确控制延时时间,不能象汇编那样直观。其实不然,对延时函数深入了解一下就能设计出一个理想的框架出来。一般的我们都用for(x=100;-x;);此句等同与x=100;while(-x);或for(x=0;x100;x+);。来写一个延时函数。在这里要特别注意:X=100,并不表示只运行100 个指令时间就跳出循环。可以看看编译后的汇编:x=100;while(-x);汇编后:movlw 100bcf 3,5bcf 3,6movwf _delayl2 decfsz _delaygoto l2re

10、turn从代码可以看出总的指令是是303 个,其公式是8+3*(X-1)。注意其中循环周期是X-1 是99 个。这里总结的是x 为char 类型的循环体,当x 为int 时候,其中受X 值的影响较大。建议设计一个char 类型的循环体,然后再用一个循环体来调用它,可以实现精确的长时间的延时。下面给出一个能精确控制延时的函数,此函数的汇编代码是最简洁、最能精确控制指令时间的:void delay(char x,char y)char z;doz=y;do;while(-z);while(-x);其指令时间为:7+(3*(Y-1)+7)*(X-1)如果再加上函数调用的call 指令、页面设定、传递

11、参数花掉的7 个指令。则是:14+(3*(Y-1)+7)*(X-1)。如果要求不是特别严格的延时,可以用这个函数:void delay()unsigned int d=1000;while(-d);此函数在4M 晶体下产生10003us 的延时,也就是10mS。如果把D 改成2000,则是20003uS,以此类推。有朋友不明白,为什么不用while(x-)后减量,来控制设定X 值是多少就循环多少周期呢?现在看看编译它的汇编代码:bcf 3,5bcf 3,6movlw 10movwf _delayl2decf _delayincfsz _delay,wgoto l2return可以看出循环体中多

12、了一条指令,不简洁。所以在PICC 中最好用前减量来控制循环体。再谈谈这样的语句:for(x=100;-x;);和for(x=0;x100;x+);从字面上看2 者意思一样,但可以通过汇编查看代码。后者代码雍长,而前者就很好的汇编出了简洁的代码。所以在PICC 中最好用前者的形式来写循环体,好的C 编译器会自动把增量循环化为减量循环。因为这是由处理器硬件特性决定的。PICC 并不是一个很智能的C 编译器,所以还是人脑才是第一的,掌握一些经验对写出高效,简洁的代码是有好处的。四、深入探讨PICC之位操作1、用位操作来做一些标志位,也就是BOOL变量可以简单如下定义:bit a,b,c;PICC会

13、自动安排一个内存,并在此内存中自动安排一位来对应a,b,c.由于我们只是用它们来简单的表示一些,信息,所以我们不需要详细的知道它们的地址位究竟是多少,只管拿来就用好了。2、要是需要用一个地址固定的变量来位操作,可以参照PIC.H里面定义寄存器。如:用内存来定义个位变量static volatile unsigned char myvar 0x25;static volatile bit b7 (unsigned)static volatile bit b6 (unsigned)static volatile bit b5 (unsigned)static volatile bit b4 (un

14、signed)static volatile bit b3 (unsigned)static volatile bit b2 (unsigned)static volatile bit b1 (unsigned)static volatile bit b0 (unsigned)这样即可以对myvar操作,也可以对直接位操作但不好的是,此招在低档片子,如系列上可能会出问题还有就是表达起来复杂,你不觉得输入代码累么?呵呵3、这也是一些常用手法#definetestbit(var, bit)(var) 测试某一位,可以做运算#definesetbit(var, bit)(var) |= (1 (bit)把某一位置#defineclrbit(var, bit)(var) 附上一段代码,可以用MPLAB调试观察i nclude “pic.h”#definetestbit(var, bit)(var) #definesetbit(var, bit)(var) |= (1 (bit)#defineclrbit(var, bit)(var) char a,b;void main()

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1