鱼C论坛

 找回密码
 立即注册
查看: 7058|回复: 5

51单片机MOV P1,55h 结果P1口上8个灯全亮

[复制链接]
发表于 2014-2-15 18:15:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 春卷の爱 于 2014-2-15 20:53 编辑

设置P1=AAh (1010 1010B),接在P1口上的8个灯,亮 灭 亮 灭 亮 灭 亮 灭
生成的机器码:85 AA 90


设置P1=55h (0101 0101B),应该是 灭 亮 灭 亮 灭 亮 灭 亮, 结果8个灯全亮。。。请问这是为什么?
生成的机器码:85 55 90

还有一个很奇怪的问题,编译生成的HEX文件,用UE打开看到的和用ISP下载工具看到的完全不一样,UE打开后好像多了很多代码,也找不到85 55 90这样的代码了
捕获.PNG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-2-19 08:37:51 | 显示全部楼层
没人知道吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-2-19 09:02:08 | 显示全部楼层
话说你是用C编写的,还是汇编编写的,我都是用C编写的,对P1口赋值是0xaa,51单片机应该是低电平点亮led灯吧,没关注过hex文件里的东西
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-19 20:25:20 | 显示全部楼层

我是用汇编编写的,就一条指令: MOV P1 0XAA, 生成3个字节的机器码。所以想不明白错误在哪里。

关于HEX的问题,我找到答案了,HEX不是简单的BIN文件的16进制表示, HEX文件也有文件头,CHECKSUM等自动生成的信息,所以不止3个字节。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-23 10:59:46 | 显示全部楼层
我知道问题了, 要改成
mov P1, #0aah
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-23 11:00:35 | 显示全部楼层
就为这我弄了半个小时, 查了ATMEL的规格书和INTEL 8051指令集. 写了一堆记录. 哈哈.

汇编:
org 0000h
mov p1, 55h
end

机器码:85 55 90
失败

C语言:
#inlucde <reg52.h>
void main()
{
    P1=0x55;
}

机器码: 0000-080F
0000:    02 08 00 00 ..     
反汇编:
02 08 00:    LJMP 08 00    跳转到地址0800
Opcode: 0x02    instruction: LJMP code addr    Bytes: 3    Flags: none

0800:    78 7F E4 F6 D8 FD 75 81 07 02 08 0C 75 90 55 22   
反汇编:
78 7F:    mov R0, 7Fh           0x78    mov R0, #data    2bytes
E4    :    CLR A                      0xE4    CLR A                   1byte                 clear register A
F6    :    mov @R0, A            0xF6    mov @R0, A        1byte
单片机mov R0, A和mov @R0, A的区别: mov R0, A 是把累加器中的数送给寄存器R0. mov @R0, A 是把累加器中的数, 送给R0内存储的地址单元. 这里是给7Fh地址赋值0
D8 FD:                                   0xD8    DJNZ R0, reladdr    2bytes        decrement and jump if not zero
R0的值-1, 等于7Eh, 判断不为0, 向前跳转3BYTE, 也就是跳过了 D8 FD, 跳过了 F6, 开始从F6执行: 给地址7Eh赋值0. 如此循环.....直到R0的值为1, 给地址01h赋值0  执行D8 FD时, R0的值-1 等于0, 执行后面的语句 (地址00h的值没有被改变). 经过以上程序, 地址01-7F的值全部为0, 不明觉厉啊

75 81 07:    mov iram addr, #data   把07h赋给internal RAM 81h;   查ATMEL的datasheet, 地址81h就是大名鼎鼎的SP (stack pointer). 难道上面那段代码是为了建立占空间? 为什么不把80h也改成0. 为什么不把00h也改成0
02 08 0C:     ljmp code addr     这句可以不要,因为080C就在下面
75 90 55:        mov iram addr, #data  把55h赋给90. 慢着, 8051instruction set关于MOV指令里有一行字:
** Note: In the case of "MOV iram addr,iram addr", the operand bytes of the instruction are stored in reverse order. That is, the instruction consisting of the bytes 0x85, 0x20, 0x50 means "Move the contents of Internal RAM location 0x20 to Internal RAM location 0x50" whereas the opposite would be generally presumed.
也就是说第一: 我上面那个汇编程序, 想把idata (55h)赋值给p1, 结果编译成了把地址55h里的值赋给90, 鬼知道地址55h里是什么数. 难怪出错. 因为没有查看8051的指令集, 想当然用了mov p1, 55h这样的赋值语句.
第二: 85这个opcode执行顺序是倒过来的, 就是把oprand 1 给oprand 2. 不过这个是机器的小癖好, 编译的时候两个操作数的顺序是倒着写的, 也就是负负为正了. 不需要特别留意.

22:                ret

成功

汇编:
org 0000h
mov p1, #55h
end

机器码: 75 90 55

成功

心得: 没有汇编, 可以问别人, 发帖子, 程序也可以修改正确, 但我永远都不知道发生了什么.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-29 23:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表