PIC单片机-PICC介绍

更新时间:2023-07-09 10:37:48 阅读: 评论:0

PIC单⽚机-PICC介绍⽬录:
⼀、如何从汇编转向PICC
⼆、浅谈PICC 的位操作
三、PICC 之延时函数和循环体优化
五、在PICC 中使⽤常数指针
六、PICC 关于unsigned 和 signed 的⼏个关键问题
七、⽤PICC 写⾼效的位移操作
⼋、C 程序优化
九、关于PIC的C语⾔中嵌⼊汇编语⾔
⼗、PICC中实现C语⾔与汇编语⾔混合编程
----------------------------------------------------------------------------------------------------------------
⼀、如何从汇编转向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;
羊肉夹馍PCL 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、
PS1、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 闪烁:
#include
void main()
{
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 变量放在⼀个内存的位中,既可以达到运算
速度快,⼜可以达到最⼤限度节省空间的⽬的。在C 中的位操作有多种选择。
*********************************************
如:char x;    x=x  |  0B00001000;
char x;    x=x & 0B11011111;
把上⾯的变成公式则是:
#define bitt(var,bitno)(var |=1<<bitno)
#define bitclr(var,bitno)(var &=~(1<<bitno))
则上⾯的操作就是:
char x;    bitt(x,4);
char x;    bitclr (x,5);
*************************************************
但上述的⽅法有缺点,就是对每⼀位的含义不直观,最好是能在代码中能直观看出每⼀位代表的意思,
这样就能提⾼编程效率,避免出错。如果我们想⽤X 的0-2 位分别表⽰温度、电压、电流的BOOL 值可以如下:
unsigned char x @ 0x20;
bit temperature@ (unsigned)&x*8+0;
bit voltage@ (unsigned)&x*8+1;
bit current@ (unsigned)&x*8+2;
这样定义后X的位就有⼀个形象化的名字,不再是枯燥的1、2、3、4 等数字了。可以对X 全局修改,也可以对每⼀位进⾏操作:char=255;
网速卡
temperature=0;
if(voltage)......
*****************************************************************
还有⼀个⽅法是⽤C 的struct 结构来定义,如:
struct cypok{
temperature:1;
voltage:1;
current:1;
none:4;
}x @ 0x20;
这样就可以⽤
if(x.current)....
等操作了。
**********************************************************
上⾯的⽅法在⼀些简单的设计中很有效,但对于复杂的设计中就⽐较吃⼒。如象在多路⼯业控制上。
前端需要分别收集多路的多路信号,然后再设定控制多路的多路输出。如:有2 路控制,每⼀路的前端信
号有温度、电压、电流。后端控制有电机、喇叭、继电器、LED。如果⽤汇编来实现的话,是很头疼的事
情,⽤C 来实现是很轻松的事情,这⾥也涉及到⼀点C 的内存管理(其实C 的最⼤优点就是内存管理)。
采⽤如下结构:
union cypok{
struct out{
motor:1;
relay:1;
speaker:1;
led1:1;
led2:1;过程所
}out;
struct in{
none:5;
temperature:1;
voltage:1;
current:1;
current:1;
}in;
char x;
阿拉弗拉海
};
union cypok an1;
union cypok an2;
上⾯的结构有什么好处呢?
细分了信号的路an1 和an2;
细分了每⼀路的信号的类型(是前端信号in 还是后端信号out):
an1.in ;
an1.out;
an2.in;
an2.out;
然后⼜细分了每⼀路信号的具体含义,如:
perature;
君士坦丁大帝;
an2.in.voltage;
an2.out.led2;等
这样的结构很直观的在2 个内存中就表⽰了2 路信号。并且可以极其⽅便的扩充。如添加更多路的信号,只需要添加:
union cypok an3;
union cypok an4;
从上⾯就可以看出⽤C 的巨⼤好处。
----------------------------------------------------------------------------------------------------------------
三、PICC 之延时函数和循环体优化
很多朋友说C 中不能精确控制延时时间,不能象汇编那样直观。其实不然,对延时函数深⼊了解⼀下
就能设计出⼀个理想的框架出来。⼀般的我们都⽤for(x=100;--x;){;}此句等同与x=100;while(--x){;};
或for(x=0;x<100;x++){;}。
来写⼀个延时函数。
露营在这⾥要特别注意:X=100,并不表⽰只运⾏100 个指令时间就跳出循环。
可以看看编译后的汇编:
x=100;while(--x){;}
汇编后:
movlw 100
bcf 3,5
bcf 3,6
movwf _delay
l2 decfsz _delay
goto l2
return
九龙海战
从代码可以看出总的指令是是303 个,其公式是8+3*(X-1)。注意其中循环周期是X-1 是99 个。这
⾥总结的是x 为char 类型的循环体,当x 为int 时候,其中受X 值的影响较⼤。建议设计⼀个char 类型的
循环体,然后再⽤⼀个循环体来调⽤它,可以实现精确的长时间的延时。下⾯给出⼀个能精确控制延时的
函数,此函数的汇编代码是最简洁、最能精确控制指令时间的:
void delay(char x,char y){
char z;
do{
z=y;
do{;}while(--z);
}while(--x);
}
其指令时间为:7+(3*(Y-1)+7)*(X-1)如果再加上函数调⽤的call 指令、页⾯设定、传递参数
茶叶保存花掉的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,5
bcf 3,6
movlw 10
movwf _delay
l2
decf _delay
incfsz _delay,w
goto l2
return
可以看出循环体中多了⼀条指令,不简洁。所以在PICC 中最好⽤前减量来控制循环体。
再谈谈这样的语句:
for(x=100;--x;){;}和for(x=0;x<100;x++){;}
从字⾯上看2 者意思⼀样,但可以通过汇编查看代码。后者代码雍长,⽽前者就很好的汇编出了简洁的代
码。所以在PICC 中最好⽤前者的形式来写循环体,好的C 编译器会⾃动把增量循环化为减量循环。因为
这是由处理器硬件特性决定的。PICC 并不是⼀个很智能的C 编译器,所以还是⼈脑才是第⼀的,掌握⼀些
经验对写出⾼效,简洁的代码是有好处的。

本文发布于:2023-07-09 10:37:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1074274.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:汇编   代码   函数   控制   内存   延时
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图