最近打算玩一下STM8, 只为了消化一下我的库存,因为我曾经买过几个型号的STM8单片机,但是一直没用来DIY啥。我对STM8熟悉程度远不如STM32, 后者是流行广泛的ARM核,STM8却是ST独家的架构。
STM8 CPU是在ST7基础上增强,有人说是从6502演变来的,我看倒也不像。学习了一下历史,Motorola的6800演变出来的6805/6811/6809三个分支,以及6502这个与6800有渊源的CPU,从寄存器和指令集上看STM8是和它们有相似之处的,不过差异的地方也很大。作为一个8位MCU,STM8的寻址范围居然达到16M byte(我不信ST会给8位机配上1M以上的ROM或RAM),寻址模式就很多了,间接内存访问比x86都复杂,看惯了RISC的CPU更不能忍。好吧,虽然指令集复杂,STM8的执行速度还快,反正不会纯用汇编来开发。
ST并没有提供STM8的C编译器(汇编器是有的),需要用第三方的。Cosmic C编译器有免费License的版本可以用,这也是ST推荐的,我就装了一个来试。ST官方支持的还有Raisonance的编译器,此外IAR也有STM8的开发环境。
试写了个C程序测试,可以用STVP连接ST-Link下载程序,但我觉得还需要个能反汇编看编译结果的东西。Cosmic工具链里面没有反汇编程序,ST的汇编工具里也没有,STVD既然能跟踪调试应该有,但我没能把它用起来。
干脆自己写一个STM8反汇编工具吧,也练下手怎么写。
先研究下STM8的指令集,这是一种典型变长指令集,除了前缀字节,操作码就在一个字节里面。于是我照着手册统计了一张表出来:
一个字节能表示的范围除了 0x90, 0x91, 0x92, 0x72 用来做指令前缀,其它几乎都用来作操作码了。当然许多指令都有多种寻址模式的(比如加法是谁和谁相加,需要指定),因此用了不止一个操作码。算上寻址模式,256种指令都不够用的,所以STM8靠前面增加前缀字节来扩展。从手册里面截一个例子如下(这是XOR指令的多种编码):
在指令的操作码后面就是提供数据或地址的字节了,长度由操作码加上前缀来决定。
编写反汇编程序就是写一个根据字节数据流的查表过程。上面我做的那个表只是划分了指令的分布,涉及到寻址模式的细节还是得一边写一边查手册。从表上看,操作码的高半字节大概可以把指令划分为几类,再用低半字节去细分指令,于是我的程序解码第一步就是一个 switch-case 结构来划分任务:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int decode_instr(unsigned char opcode) { switch(opcode>>4) { case 1: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: return decode_group1(opcode); case 0: case 3: case 4: case 6: case 7: return decode_group2(opcode); case 5: if(Prefix==0x72) return decode_group2(opcode); else return decode_5x(opcode); case 8: return decode_8x(opcode); case 2: return decode_2x(opcode); case 9: return decode_9x(opcode); default: return -1; } } |
解码的结果是放到全局变量里面的,返回值只代表了指令是否有效。例如,表格最右边一列的指令我是这样解析的:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | int decode_9x(unsigned char opcode) { AutoXY=1; switch(opcode&0x0f) { case 0: return set_prefix(0x90); case 1: return set_prefix(0x91); case 2: return set_prefix(0x92); case 3: format(0, LDW, regX, regY); format(0x90, LDW, regY, regX); return 1; case 4: format(0, LDW, regSP, regX); return 1; case 5: format(0, LD, regXH, regA); return 1; case 6: format(0, LDW, regX, regSP); return 1; case 7: format(0, LD, regXL, regA); return 1; case 8: format(0, RCF, 0, 0); return 1; case 9: format(0, SCF, 0, 0); return 1; case 0xA: format(0, RIM, 0, 0); return 1; case 0xB: format(0, SIM, 0, 0); return 1; case 0xC: format(0, RVF, 0, 0); return 1; case 0xD: format(0, NOP, 0, 0); return 1; case 0xE: format(0, LD, regA, regXH); return 1; case 0xF: format(0, LD, regA, regXL); return 1; default: return -1; } } |
主要是靠 format() 函数根据当前的指令前缀来翻译操作码:指令名称,寻址的第一操作数、第二操作数。若一共写 256 个 case 分支就太繁琐了,需要抓住共性,像表格中绿色背景的这一组指令我是这么处理的:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | int decode_group2(unsigned char opcode) { int instr; AutoXY=1; switch(opcode&0x0f) { case 1: switch(opcode>>4) { case 0: format(0, RRWA, regX, 0); return 1; case 3: format(0, EXG, regA, longmem); return 1; case 4: format(0, EXG, regA, regXL); return 1; case 6: format(0, EXG, regA, regYL); return 1; default: return -1; } break; case 2: switch(opcode>>4) { case 0: format(0, RLWA, regX, 0); return 1; case 3: format(0, POP, longmem, 0); return 1; case 4: format(0, MUL, regX, regA); return 1; case 6: format(0, DIV, regX, regA); return 1; case 7: return set_prefix(0x72); } break; case 5: switch(opcode>>4) { case 3: format(0, MOV, longmem, imm8); return 1; case 4: format(0, MOV, mem, mem); return 1; case 6: format(0, DIVW, regX, regY); return 1; default: return -1; } break; case 0xB: switch(opcode>>4) { case 3: format(0, PUSH, longmem, 0); return 1; case 4: format(0, PUSH, imm8, 0); return 1; case 6: format(0, LD, offSP, regA); return 1; 关键字:STM8 反汇编工具 引用地址:徒手编写了一个STM8的反汇编工具
上一篇:STM8单片机CAN滤波器的设置 推荐阅读最新更新时间:2024-11-17 16:07
STM8 单工通信
STM8 单工通信 SPI能够以两种配置工作于单工方式: 1条时钟线和1条双向数据线 1条时钟线和1条数据线(双工或接收方式) 1条时钟线和1条双向数据线 设置SPI_CR2寄存器中的BDM位启用此模式。在这个模式中,SCK用作时钟,主模式中的MOSI或从模式中的MISO用作数据通信。 传输的方向(输入或输出)由SPI_CR2寄存器里的BDOE控制,当这个位是1的时候,数据线是输出,否则是输入。 1条时钟和1条数据线(双工或只接收方式) 为了释放一根I/O脚作为它用,可以通过设置SPI_CR2寄存器中的RXONLY位来禁止SPI输出功能。这样的话,SPI将运行于只接收模式。当RXONLY位置0时,SPI又会恢复到全
[单片机]
STM8 多处理器通信
STM8 多处理器通信 通过UART可以实现多处理器通信(将几个UART连在一个网络里)。例如某个UART设备可以是主设备,它的TX输出和其他UART从设备的RX输入相连接;UART从设备的各自TX输出作逻辑与运算后和主设备的RX输入相连接。 在多处理器配置中,我们通常希望只有被寻址的接收者才被激活,来接收随后的数据,这样就可以减少由未被寻址的接收器的参与带来的多余的UART服务开销。 未被寻址的设备可启用其静默功能置于静默模式。在STM8静默模式里: 任何接收状态位都不会被设置。 所有接收中断被禁止。 UART_CR1寄存器中的RWU位被置1。RWU可以被硬件自动控制或在某个特定条件下由软件写入。 根据UAR
[单片机]
STM8学习笔记---新建IAR工程文件
1.打开IAR工具 2.选择Project—Create New Project 3.选择Empty project,点击OK。 4.选择文件存储路径,输入工程名,点保存按钮。 5单击左上角新建文件按钮 这时候右侧会出现一个新建文件,新建的是文本文件,需要把文本文件保存为*.c格式。 5.点左上角保存按钮 6.将文件名改为main.c,点保存按钮。 这时候界面右侧文件名就会变为main.c,但是新建的工程中还没有文件,需要将main.c文件添加到工程中。 7.在左侧新建工程名上单机鼠标右键,选择Add–Add Files 8.然后再打开的文件框中选中main.c文件,然后点打开。 这时候工程文件
[单片机]
STM8 入门学习与实验(一)GPIO与UART
简介:这一章节将描述如何配置GPIO,以及如何配置UART STM8工程模版:http://download.csdn.net/detail/u012388993/9904051 这两则实验将使用到的基本的系统配置初始化函数 CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);//配置UART1时钟 CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);配置时钟分频为1,则系统时钟频率为16Mhz/1 = 16Mhz CLK_HSICmd(ENABLE);//使能内部振荡器 实验一、点亮LED灯,灯正极接电源负极连接到引
[单片机]
STM8的AWU应用体会
AWU——STM8中的精简RTC 今天使用STM8L001进行了类似RTC定时从停止模式唤醒MCU的实验。不知为何,在STM8S系列部分芯片(我没一个个去查看)和STM8L001、STM8L101等个别芯片上是没有RTC模块的,取而代之的是其阉割版 —— AWU模块。 因为只能配置自动唤醒闹钟,没有设置日历的功能。 这个AWU看文档配置起来极其简单,但实际操作起来还是有些坑的。我以实验用的STM8L001为例。 文档说第一步要测量LSI的时钟频率。 后面的步骤在库文件的AWU_Init函数中都已经有了过程。 怎么测量LSI的时钟频率呢? 这写的一堆是干嘛呢…我比较懒,就去库文件中找了找,发现了几个好东西。 在s
[单片机]
STM8 GPIO输入输出模式
悬浮输入 悬浮输入,也叫浮空输入,顾名思义,即引脚悬空。这种方式的输入阻抗很高。当悬浮输入的引脚上加上信号时,单片机所得到的信号并不确定是高电平或是低电平,是一个不确定的信号。悬浮输入的典型应用就是模数转换,外部的任何一个小信号都要经过A/D采样转换为数字信号。 上拉输入 上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平!电阻同时起限流作用!强弱只是上拉电阻的阻值不同。 上拉输入最典型的应用就是外部按键,当按键未按下时,我们要保证它是高电平,当按键按下时才被拉低。 推挽输出 推挽输出(Push-pull output),也称为互补输出,推拉式输出。推挽输出模式导通损耗小,效率高。在此
[单片机]
STM8与汇编语言(15)--AD转换
现在大部分的单片机也都具备了A/D转换器,有8位的,也有10位的,当然性能好的具备了12位的A/D。在STM8单片机中,提供的是10位的A/D,通道数随芯片不同而不同,少的有4个通道,多的则有16个通道。 下面的实验程序首先对A/D输入进行采样,然后将采样结果的高8位(丢弃最低的2位),作为延时参数去调用延时子程序,然后再去驱动LED控制信号。因此不同的采样值,决定了LED的闪烁频率。当旋转ST三合一开发板上的电位器时,可以看到LED的闪烁频率发生变化。 同样还是利用ST的开发工具,生成一个汇编程序的框架,然后修改其中的main.asm,修改后的代码如下。 stm8/ #include mapping.inc
[单片机]
【STM8】IAR 项目新建步骤
一、新建项目目录和子文件夹 新建如下文件夹名: 二、将 STM8 库文件放入到 LIB 里 STM8 库文件如下: 三、新建 IAR 项目 3.1 新建项目 打开 IAR 软件,新建项目:Project - Create New Project ... 将项目文件保存到第一步新建的的 “IAR” 目录中,文件名可以直接按照项目的名称命名。 3.2 在IAR项目增加组 在 IAR 软件的项目中分别增加三个组:DRV、LIB、USR(和第一步新建的目录相对应) 3.3 设置项目参数 ▪ 选择开发的芯片 ▪ 设置预处理的文件夹 文本内容如下: $PROJ_DIR$ $PROJ_DIR$..LI
[单片机]
推荐帖子
小广播
推荐内容
热门活动
换一批 更多
设计资源 培训 开发板 精华推荐
最新单片机文章
更多开源项目推荐
更多精选电路图
更多热门文章
更多每日新闻
更多往期活动
11月22日历史上的今天
厂商技术中心
|