|
楼主 |
发表于 2013-11-13 14:39:18
|
显示全部楼层
本帖最后由 oldbeginner 于 2013-11-13 15:07 编辑
映射表有4种,
code (*key_list[16])();
code (*key_list_1[12][2])();
code (*key_list_2[14][2])();
code (*key_list_3[256])();
因为我打算实现的功能简单,所以只接触第一种最简单的映射,而且16个元素只会用到4个。
code (*key_list[16])()={
CMDFNC , // 0 (FNC应用指令)
CMDP , // 1 (P 应用指令)
LD , // 2 (LD指令, 5000+ppp, 扩展 Mp除外)
LDI , // 3 (LDI指令, 5000+ppp, 扩展 Mp除外)
AND , // 4 (AND指令, 5000+ppp, 扩展 Mp除外)
ANI , // 5 (ANI指令, 5000+ppp, 扩展 Mp除外)
OR , // 6 (OR指令, 5000+ppp, 扩展 Mp除外)
ORI , // 7 (ORI指令, 5000+ppp, 扩展 Mp除外)
CMDER , // 8 (多字指令,第二字及以后有效)
CMDER , // 9
CMDER , // A (多字指令,第二字及以后有效, 仅对M1536-M3071有效,需加偏移量200)
CMDER , // B (Pn指令, 仅对CJ,CALL有效)
OUTYM , // C (OUT指令, 仅对Y,M有效)
SETYM , // D (SET指令, 仅对Y,M有效)
RSTYM , // E (RST指令, 仅对Y,M有效)
CMDCH }; // F (纯单字指令)
为什么用code,
1,把段码放在code里,是为了节省RAM。如果放在前256字节内,查表时只要八位地址即可,所以会快些。ROM读取不会慢。单片机执行的每一条指令都是从ROM区读取的。
ROM区的内容是只读的,所以你不能将改变(程序运行中改变)的数组放进去。http://zhidao.baidu.com/question ... l=relate_question_1
不理解为什么没有unsigned int或unsigned char搭配code。先继续。
*****************************************************************
先看一下代码中的定义
#define CODE_START 0x8000 // PLC执行代码缓冲区首地址
但是另外还有一个
unsigned char code CODE_START[PLCSTEP*4] = {0x0,0x24,0x8,0x0,0x0,0x88,0x0,0x28,0x0,0xd5,0x1,0x24,0x9,
0x0,0x1,0x88,0x1,0x28,0x0,0xe5,0xca,0x1,0x2,0x84,0x2,0xc8,0x2,0x28,0x1,0xd5,0xcb,0x1,0x2,0x84,0x3,
0xc8,0x3,0x28,0x1,0xe5,0x0f,0x0
};
两者是什么关系?怎样联系?先继续
volatile unsigned char code *CODE_p;
1、然后理解第1句代码,
CODE_p = (unsigned char code *)CODE_START;
就是让CODE_p指向PLC执行代码缓冲区
2、第2句, Pi = 0x01;
volatile unsigned int data Pi;
因为Pi是16位的数,所以Pi=0x0001,作用应该在下面了解。
3、最后是do while循环。先看循环体,最后看循环条件。
循环体
orderL = *CODE_p;
CODE_p++;
orderH = *CODE_p;
CODE_p++;
ppp = order & 0xfff;
(*key_list[orderH >> 4])();
4、看定义
#define orderL order0.BYTES.BYTEL // 命令位地址缓冲区低位
#define orderH order0.BYTES.BYTEH // 命令位地址缓冲区高位
还要再看order0的定义
volatile TYPE_BYTES_WORD xdata order0;
还要再看TYPE_BYTES_WORD的定义
typedef union { //重点注意C编辑器的多字节变量类型的高低字节前后排列次序
struct { unsigned char BYTEH; //可以按字节寻址
unsigned char BYTEL; //可以按字节寻址
}BYTES;
unsigned int WORD; //可以按字寻址
}TYPE_BYTES_WORD; //定义一个既能按字节寻址也可按字寻址的新变量类型
类似笔记02中的联合体,幸亏当时理解了,现在难度就减小了。
用同样的方法来理解,
unsigned char orderL
unsigned char orderH
将orderL和orderH都理解位8位无符号数,他俩又可以组成一个字。
5、 orderL = *CODE_p;
CODE_p++;
orderH = *CODE_p;
CODE_p++;
很好理解,利用CODE_p把PLC缓冲区的内容赋值给orderL和orderH。
6、 ppp = order & 0xfff;
先看定义
volatile unsigned int ppp;
#define order order0.WORD // 命令位地址缓冲区
order就是由orderL和orderH合并而成的,根据一、标注说明:注释2pp 为32位寄存器名称编号,表示为十进制数,但在存储格式中以十六进制数 ppp 表示。
所以把order和0xfff与一下,然后赋值给ppp。
实例,指令LD X002,指令码为24 02,存储格式为02 24,转换成 ASCII 码传送为30 32 32 34。
则orderL=0x30
orderH=0x32
利用联合体概念, order=0x3230,则ppp=0x0230。
7、 (*key_list[orderH >> 4])();
利用实例来理解,orderH向右移4位,则orderH=0x03,这里不是很理解。如果向左移,才有意义。这样orderH=0x02
然后*key_list[orderH >> 4]=*key_list[2]=LD。
此时调用了LD函数,下一步再理解LD函数,目前只需了解通过映射表,LD函数被调用了。
void LD (void) // 2 (LD指令, 2000+ppp, 扩展 Mp除外)
{ ACC_BIT <<= 1;
ACC_BIT |= RD_ppp(ppp);
}
8、最后是循环条件while((CODE_p < CODE_END) && (CODE_p != CODE_START));
根据字面意思就很好理解,不是开头和并且未到末尾就待在循环体中。
***************************************************
|
|