51单片机(STC89C52)在Ubuntu下的开发
2021/7/11 7:09:30
本文主要是介绍51单片机(STC89C52)在Ubuntu下的开发,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
硬件准备
- 使用常见的C51最小开发板
- 一个USB2TTL的转接卡
- 用于查看输出的LED+1K限流电阻
在Ubuntu20.04下的开发
软件部分
- 编译工具 SDCC http://sdcc.sourceforge.net/
- 烧录工具 stcgal https://github.com/grigorig/stcgal
安装sdcc
Ubuntu20.04自带的sdcc版本为3.8.0, 所以打算自行编译安装. 先阅读sdcc的安装说明, 在 http://sdcc.sourceforge.net/doc/sdccman.pdf
- 前往 https://sourceforge.net/projects/sdcc/files/sdcc/4.1.0/ 下载最新的4.1.0源码.
- 解压
tar -xvjf sdcc-src-4.1.0.tar.bz2
- 配置
./configure
, 过程中提示gputils需要安装, 通过apt install gputils
安装, 再次./configure
未再报错, 但是提示这个gputils比较旧, 有些设备不支持, 先忽略 - 编译
make
, 过程中提示缺texinfo, 通过apt install texinfo
安装, 然后再make. 需要说一下的是编译时间很长, 如果仅仅需要编译C51, 可以在配置时禁掉其他一些不需要的芯片. - 安装
sudo make install
检查和测试安装好的sdcc
- 执行
sdcc --version
看看输出是否正确, 执行sdcc --print-search-dirs
查看库文件的位置. 默认的8051的库文件位置为/usr/local/share/sdcc/include/mcs51/
- 写一段代码test001.c,
char test; void main(void) { test = 0; }
用sdcc编译, 如果生成结果文件正常没有报错, 就说明安装没问题
# 这一步会产生test001.asm等文件 sdcc -c test001.c # 这一步会产生test001.ihx等文件 sdcc test001.c
安装stcgal
根据Github上项目首页的说明, 直接用pip3 install stcgal
安装, 然后执行stcgal -h
查看输出
编写代码并用sdcc编译
编写一个test002.c, 通过控制占空比让P0.7上的LED产生呼吸灯的效果. 8052.h是sdcc自带的通用的C52头文件, 不是STC89C52的定制头文件
#include <8052.h> #define Led10 P0_7 typedef unsigned int u16; int atime = 64; void delay(u16 pms) { u16 x, y; for (x=pms; x>0; x--) { for (y=11; y>0; y--); } } void ledfade(u16 i) { Led10 = 0; delay(i); Led10 = 1; delay(atime-i); } int main(void) { u16 a, b; while(1) { for (a=0; a<atime; a++) { for (b=0; b < (atime - a)/4; b++) { ledfade(a); } } for (a=atime; a>0; a--) { for (b=0; b < (atime - a)/4; b++) { ledfade(a); } } } }
编译有两种方式
- 加上
-m<port>
参数, 对应89C52, 用-mmcs51
, 如果是Makefile, 加到CCFLAG里面 - 不加参数, 在头文件中指定路径, 例如
#include <mcs51/8052.h>
这是使用参数的方式
sdcc -mmcs51 test002.c
烧录
烧录使用stcgal, 这个页面下有详细的使用方法
stcgal -P stc89 test002.ihx Waiting for MCU, please cycle power: done # 这里要关闭再打开电源 Target model: Name: STC89C52RC/LE52R Magic: F002 Code flash: 8.0 KB EEPROM flash: 6.0 KB Target frequency: 11.010 MHz Target BSL version: 3.2C Target options: cpu_6t_enabled=False bsl_pindetect_enabled=False eeprom_erase_enabled=False clock_gain=high ale_enabled=True xram_enabled=True watchdog_por_enabled=False Loading flash: 243 bytes (Intel HEX) Switching to 19200 baud: checking setting testing done Erasing 2 blocks: done Writing flash: 640 Bytes [00:00, 1844.10 Bytes/s] Setting options: done Disconnected!
烧录完就会自动运行. 默认的波特率为19200, 写入较慢, 对于STC89C52RC可以直接使用115200的波特率, 用-b
参数指定
stcgal -P stc89 -b 115200 test002.ihx
如果同时有多个com口, 用-p
指定端口
stcgal -P stc89 -b 115200 dist/89/89.hex -p /dev/ttyUSB1
使用-D
参数能显示出串口的交互信息
stcgal -D -P stc89 -b 115200 test002.ihx Waiting for MCU, please cycle power: <- Packet data: 46 B9 68 00 1C 00 0A 76 0A 72 0A 76 0A 72 0A 76 0A 72 0A 76 0A 72 32 43 FD F0 02 82 5A 16 done Target model: Name: STC89C52RC/LE52R Magic: F002 Code flash: 8.0 KB EEPROM flash: 6.0 KB Target frequency: 11.010 MHz Target BSL version: 3.2C Target options: cpu_6t_enabled=False bsl_pindetect_enabled=False eeprom_erase_enabled=False clock_gain=high ale_enabled=True xram_enabled=True watchdog_por_enabled=False Loading flash: 337 bytes (Intel HEX) Switching to 115200 baud: checking -> Packet data: 46 B9 6A 00 0C 8F FF FD 00 06 A0 81 28 16 <- Packet data: 46 B9 68 00 0C 8F FF FD 00 06 A0 81 26 16 setting -> Packet data: 46 B9 6A 00 0B 8E FF FD 00 06 A0 A5 16 <- Packet data: 46 B9 68 00 0B 8E FF FD 00 06 A0 A3 16 testing -> Packet data: 46 B9 6A 00 0C 80 00 00 36 01 F0 02 1F 16 <- Packet data: 46 B9 68 00 06 80 EE 16 -> Packet data: 46 B9 6A 00 0C 80 00 00 36 01 F0 02 1F 16 <- Packet data: 46 B9 68 00 06 80 EE 16 -> Packet data: 46 B9 6A 00 0C 80 00 00 36 01 F0 02 1F 16 <- Packet data: 46 B9 68 00 06 80 EE 16 -> Packet data: 46 B9 6A 00 0C 80 00 00 36 01 F0 02 1F 16 <- Packet data: 46 B9 68 00 06 80 EE 16 done Erasing 2 blocks: -> Packet data: 46 B9 6A 00 0D 84 02 33 33 33 33 33 33 2F 16 <- Packet data: 46 B9 68 00 06 80 EE 16 done -> Packet data: 46 B9 6A 00 8C 00 00 00 00 00 00 80 02 00 06 02 00 AC 75 81 09 12 01 4D E5 82 60 03 02 00 03 79 00 E9 44 00 60 1B 7A 00 90 01 51 78 01 75 A0 00 E4 93 F2 A3 08 B8 00 02 05 A0 D9 F4 DA F2 75 A0 FF E4 78 FF F6 D8 FD 78 00 E8 44 00 60 0A 79 01 75 A0 00 E4 F3 09 D8 FC 78 00 E8 44 00 60 0C 79 00 90 00 01 E4 F0 A3 D8 FC D9 FA 75 08 40 75 09 00 02 00 03 AE 82 AF 83 EE 4F 60 14 7C 0B 7D 00 1C BC FF 01 1D EC 4D 70 F7 1E BE FF FB 16 <- Packet data: 46 B9 68 00 07 80 85 74 16 Writing flash: 0%| | 0/512 [00:00<?, ? Bytes/s]-> Packet data: 46 B9 6A 00 8C 00 00 00 00 80 00 80 01 1F 80 E8 22 AE 82 AF 83 C2 87 8E 82 8F 83 C0 07 C0 06 12 00 68 D0 06 D0 07 D2 87 AC 08 AD 09 EC C3 9E F5 82 ED 9F F5 83 02 00 68 7E 00 7F 00 AC 08 AD 09 C3 EE 9C EF 9D 50 45 7C 00 7D 00 AA 08 AB 09 EA C3 9E FA EB 9F C3 13 CA 13 CA C3 13 CA 13 CA FB C3 EC 9A ED 9B 50 1E 8E 82 8F 83 C0 07 C0 06 C0 05 C0 04 12 00 85 D0 04 D0 05 D0 06 D0 07 0C BC 00 C9 0D 80 C6 0E BE 00 B3 0F 80 B0 14 16 <- Packet data: 46 B9 68 00 07 80 1E 0D 16 -> Packet data: 46 B9 6A 00 8C 00 00 00 01 00 00 80 AE 08 AF 09 EE 4F 60 A4 7C 00 7D 00 AA 08 AB 09 EA C3 9E FA EB 9F C3 13 CA 13 CA C3 13 CA 13 CA FB C3 EC 9A ED 9B 50 1E 8E 82 8F 83 C0 07 C0 06 C0 05 C0 04 12 00 85 D0 04 D0 05 D0 06 D0 07 0C BC 00 C9 0D 80 C6 1E BE FF 01 1F 80 B7 75 82 00 22 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF AD 16 <- Packet data: 46 B9 68 00 07 80 36 25 16 Writing flash: 75%|█████████████████████████▌ | 384/512 [00:00<00:00, 3814.67 Bytes/s]-> Packet data: 46 B9 6A 00 8C 00 00 00 01 80 00 80 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 77 16 <- Packet data: 46 B9 68 00 07 80 80 6F 16 Writing flash: 640 Bytes [00:00, 4207.06 Bytes/s] Setting options: -> Packet data: 46 B9 6A 00 0A 8D FD FF FF FF FB 16 <- Packet data: 46 B9 68 00 0A 8D FD FF FF FF F9 16 done -> Packet data: 46 B9 6A 00 06 82 F2 16 Disconnected!
SDCC 下的串口
开启串口, 并将putchar()重定向到串口
头文件serial.h
#ifndef __SERIAL_H__ #define __SERIAL_H__ #include <mcs51/8051.h> void serial_init(void); #endif // __SERIAL_H__
C文件serial.c
#include "serial.h" void serial_init(void) { // configure serial for 9600 baud, 8 data bits, 1 stop bit. TMOD = 0x21; SCON = 0x40; // TH1 = 256 - 11.0592 * 1000 * 1000 / 12 / 32 / 9600; TH1 = 0xFD; // start the timer1 TCON |= 0x40; // tell putchar() the serial is ready to send SCON |= 0x02; }
SDCC下的时钟中断
用11.0592MHz晶振的C52产生较精确的1秒定时中断, 下面的代码是基于SDCC的8052.h, 定时器初始值由如下计算得到
- 由晶振11.0592 MHz, 得到定时器时钟为 11.0592 / 12 = 0.9216 MHz,
- 因此1ms对应 921.6 个时钟周期,
- 因此50ms对应 46080 个时钟周期,
- 将其设为一次中断后, 20次中断就对应1s
代码
#include <8052.h> const unsigned char th = (65536 - 46080) / 256; const unsigned char tl = (65536 - 46080) % 256; volatile unsigned char i = 0; void main() { TMOD= 0x01; //工作方式为16位定时器 TH0 = th; //计数寄存器高8位 TL0 = tl; //计数寄存器低8位 EA = 1; //允许中断 ET0 = 0x01; //允许T0中断 TR0 = 1; //启动T0 while(1); } void Timer0IRQ(void) __interrupt (1) // 中断处理函数 T0 -> 中断1 { i++; if(i > 20) { P0_7 = (P0_7 == 1)? 0 : 1; //触发P0.7 LED闪烁 i = 1; // 注意这边不能初始化为0, 否则每次会多跑一个中断 } TH0 = th; //计数寄存器高8 位重新载入 TL0 = tl; //计数寄存器低8 位重新载入 }
参考
- Very helpful SDCC C51 code examples https://github.com/hungtcs-lab/8051-examples
这篇关于51单片机(STC89C52)在Ubuntu下的开发的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享