前言
我使用的开发板为普中的 SC89C52RC
在家里使用 PC 进行学习,在公司使用 Mac 进行学习,所以才有了此篇文章。
1.ch340串口驱动安装
官方没有 Mac 版本的 CH340 的驱动,但是 CH341 是兼容 CH340 的,所以我们去官网去下载 CH341 的驱动。
下载地址:https://www.wch.cn/download/CH341SER_MAC_ZIP.html
打开 pkg 安装即可。
在完成安装后,将开发板连接至 Mac。在终端中输入:ls /dev/tty.wchusb*,
若出现了类似的文字 /dev/tty.wchusbserial110 那么恭喜你,驱动程序的安装已经完成。
(后面的数字会根据你连接 Mac 的接口位置不同而产生变化)
2. stcgl 的安装
2.1 什么是stcal
stcgal 是一款烧录工具,利用他可以将我们的代码通过串口方式烧录到板子上。
stcgal 的 github 地址:https://github.com/grigorig/stcgal
2.2 Python3 的安装
(已安装可跳过 / 当然你也可使用 brew install python 进行安装,这里演示的是使用官方 pkg 的安装方法)
咱们随便选择一个版本下载安装即可,我这里使用的是 Python 3.10.10
下载地址:https://www.python.org/downloads/release/python-31010/
页面拉到最下面选择 Mac 的版本下载
同样双击打开安装
安装完成后可打开终端,输入 python -V 查看是否安装完成
2.3 安装 stcgl
在终端中输入 pip3 install stcgal 等待即可完成安装
3.VSCode 安装PlatformIO
在 VSCode 的扩展商店搜索 PlatformIO,并安装
安装完成后重启,随后打开 PlatformIO 那一栏。首次安装 PlatformIO 将会下载它启动 Core 需要的依赖(侧边栏会说明正在启动 Core,右下角会有小窗口的下载提示),下载完成后重启VSCode 即可。
打开 PlatformIO 那一栏后,在打开的窗口中我们选择新建项目
按照提示创建
在 src 目录下创建入口文件就可以啦
4.编译与下载
4.1 编译
在 Mac 上与 PC 的Keil 不同的是,我们这里include 的是 <8052.h> 或者 <8051.h>
我们这里写一个点灯看看
写好代码后,按快捷键 command + shift + b 或者选择 PlatformIO 的侧边栏选择 Default 单击 Build
即可进行编译。编译好的 hex 文件会放在项目目录下的 .pio 里,那个 firmware.hex 就是编译后的文件
4.2 下载
我们将会使用前面安装好的 stcgal 进行下载,打开终端输入命令
stcgal -P stc89 -p /dev/cu.wchusbserial110 /Users/biandan/Desktop/51MCU/TEST_Project/.pio/build/STC89C52RC/firmware.hex
关于命令的说明:
设备位置:前面通过 ls /dev/tty.wchusb* 获取到的那串
hex 文件路径:项目目录下的 ./.pio/build/STC89C52RC/firmware.hex
stcgal -P stc89 -p <设备位置> <hex 文件路径>
5. 延伸
个人觉得 #include <8052.h> 的不是很好用,这里提供一下我在网上搜索到的头文件
compiler.h 和 STC89XX.h
使用时 #include "STC89XX.h" 就可以了
- compile.h :支持SFR SBIT等操作符
- STC89XX.h : 单片机寄存器相关定义
文件下载链接: https://pan.baidu.com/s/1yEsdqFwNyFw2iMGsUDDasQ?pwd=qikv 提取码: qikv
compiler.h
/*------------------------------------------------------------------------- compiler.h Copyright (C) 2006, Maarten Brock, sourceforge.brock@dse.nl Portions of this file are Copyright 2014 Silicon Laboratories, Inc. http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this library; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, if you link this library with other files, some of which are compiled with SDCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. -------------------------------------------------------------------------*/ /* * Header file to overcome 8051 compiler differences for specifying * special function registers. The following compilers are supported: * SDCC, Keil, Raisonance, IAR, Hi-Tech, Tasking, Crossware, Wickenhaeuser. * Unfortunately not for use with Dunfield. The compilers are identified by * their unique predefined macros. See also: * http://predef.sourceforge.net/precomp.html * * SBIT and SFR define special bit and special function registers at the given * address. SFR16 and SFR32 define sfr combinations at adjacent addresses in * little-endian format. SFR16E and SFR32E define sfr combinations without * prerequisite byte order or adjacency. None of these multi-byte sfr * combinations will guarantee the order in which they are accessed when read * or written. * SFR16X and SFR32X for 16 bit and 32 bit xdata registers are not defined * to avoid portability issues because of compiler endianness. * SFR16LEX is provided for 16 bit little endian xdata registers. It is usable * on little endian compilers only; on big endian compilers, these registers * will not be defined. * This file is to be included in every microcontroller specific header file. * Example: * * // my_mcu.h: sfr definitions for my mcu * #include * * SBIT (P0_1, 0x80, 1); // Port 0 pin 1 * * SFR (P0, 0x80); // Port 0 * * SFRX (CPUCS, 0xE600); // Cypress FX2 Control and Status register in xdata memory at 0xE600 * * SFR16 (TMR2, 0xCC); // Timer 2, lsb at 0xCC, msb at 0xCD * * SFR16E(TMR0, 0x8C8A); // Timer 0, lsb at 0x8A, msb at 0x8C * * SFR32 (MAC0ACC, 0x93); // SiLabs C8051F120 32 bits MAC0 Accumulator, lsb at 0x93, msb at 0x96 * * SFR32E(SUMR, 0xE5E4E3E2); // TI MSC1210 SUMR 32 bits Summation register, lsb at 0xE2, msb at 0xE5 * */ #ifndef COMPILER_H #define COMPILER_H /** SDCC - Small Device C Compiler * http://sdcc.sf.net */ typedef enum {true=1,false=0}bool; #if defined (SDCC) || defined (__SDCC) # define SBIT(name, addr, bit) __sbit __at(addr+bit) name # define SFR(name, addr) __sfr __at(addr) name # define SFRX(name, addr) __xdata volatile unsigned char __at(addr) name # define SFR16(name, addr) __sfr16 __at(((addr+1U)<<8) | addr) name # define SFR16E(name, fulladdr) __sfr16 __at(fulladdr) name # define SFR16LEX(name, addr) __xdata volatile unsigned short __at(addr) name # define SFR32(name, addr) __sfr32 __at(((addr+3UL)<<24) | ((addr+2UL)<<16) | ((addr+1UL)<<8) | addr) name # define SFR32E(name, fulladdr) __sfr32 __at(fulladdr) name # define INTERRUPT(name, vector) void name (void) __interrupt (vector) # define INTERRUPT_USING(name, vector, regnum) void name (void) __interrupt (vector) __using (regnum) // NOP () macro support #define NOP() __asm NOP __endasm /** Keil C51 * http://www.keil.com */ #elif defined __CX51__ # define SBIT(name, addr, bit) sbit name = addr^bit # define SFR(name, addr) sfr name = addr # define SFRX(name, addr) volatile unsigned char xdata name _at_ addr # define SFR16(name, addr) sfr16 name = addr # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ # define INTERRUPT(name, vector) void name (void) interrupt vector # define INTERRUPT_USING(name, vector, regnum) void name (void) interrupt vector using regnum // NOP () macro support extern void _nop_ (void); #define NOP() _nop_() /** Raisonance * http://www.raisonance.com */ #elif defined __RC51__ # define SBIT(name, addr, bit) at (addr+bit) sbit name # define SFR(name, addr) sfr at addr name # define SFRX(name, addr) xdata at addr volatile unsigned char name # define SFR16(name, addr) sfr16 at addr name # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ # define INTERRUPT(name, vector) void name (void) interrupt vector # define INTERRUPT_USING(name, vector, regnum) void name (void) interrupt vector using regnum // NOP () macro support -- NOP is opcode 0x00 #define NOP() asm { 0x00 } /** IAR 8051 * http://www.iar.com */ #elif defined __ICC8051__ # define SBIT(name, addr, bit) __bit __no_init volatile bool name @ (addr+bit) # define SFR(name, addr) __sfr __no_init volatile unsigned char name @ addr # define SFRX(name, addr) __xdata __no_init volatile unsigned char name @ addr # define SFR16(name, addr) __sfr __no_init volatile unsigned int name @ addr # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) __sfr __no_init volatile unsigned long name @ addr # define SFR32E(name, fulladdr) /* not supported */ # define _PPTOSTR_(x) #x # define _PPARAM_(address) _PPTOSTR_(vector=address * 8 + 3) # define _PPARAM2_(regbank) _PPTOSTR_(register_bank=regbank) # define INTERRUPT(name, vector) _Pragma(_PPARAM_(vector)) __interrupt void name(void) # define INTERRUPT_USING(name, vector, regnum) _Pragma(_PPARAM2_(regnum)) _Pragma(_PPARAM_(vector)) __interrupt void name(void) extern __intrinsic void __no_operation (void); #define NOP() __no_operation() /** Tasking / Altium * http://www.altium.com/tasking */ #elif defined _CC51 # define SBIT(name, addr, bit) _sfrbit name _at(addr+bit) # define SFR(name, addr) _sfrbyte name _at(addr) # define SFRX(name, addr) _xdat volatile unsigned char name _at(addr) #if _CC51 > 71 # define SFR16(name, addr) _sfrword _little name _at(addr) #else # define SFR16(name, addr) /* not supported */ #endif # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ # define INTERRUPT(name, vector) _interrupt (vector) void name (void) # define INTERRUPT_USING(name, vector, regnum) _interrupt (vector) _using(regnum) void name (void) // NOP () macro support extern void _nop (void); #define NOP() _nop() /** Hi-Tech 8051 * http://www.htsoft.com */ #elif defined HI_TECH_C # define SBIT(name, addr, bit) volatile bit name @ (addr+bit) # define SFR(name, addr) volatile unsigned char name @ addr # define SFRX(name, addr) volatile far unsigned char name @ addr # define SFR16(name, addr) /* not supported */ # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ # define INTERRUPT(name, vector) void name (void) interrupt vector # define INTERRUPT_PROTO(name, vector) // NOP () macro support #define NOP() asm(" nop ") /** Crossware * http://www.crossware.com */ #elif defined _XC51_VER # define SBIT(name, addr, bit) _sfrbit name = (addr+bit) # define SFR(name, addr) _sfr name = addr # define SFRX(name, addr) volatile unsigned char _xdata name _at addr # define SFR16(name, addr) _sfrword name = addr # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ /** Wickenhaeuser * http://www.wickenhaeuser.de */ #elif defined __UC__ # define SBIT(name, addr, bit) unsigned char bit name @ (addr+bit) # define SFR(name, addr) near unsigned char name @ addr # define SFRX(name, addr) xdata volatile unsigned char name @ addr # define SFR16(name, addr) /* not supported */ # define SFR16E(name, fulladdr) /* not supported */ # define SFR16LEX(name, addr) /* not supported */ # define SFR32(name, fulladdr) /* not supported */ # define SFR32E(name, fulladdr) /* not supported */ /** default * unrecognized compiler */ #else # warning unrecognized compiler # define SBIT(name, addr, bit) volatile bool name # define SFR(name, addr) volatile unsigned char name # define SFRX(name, addr) volatile unsigned char name # define SFR16(name, addr) volatile unsigned short name # define SFR16E(name, fulladdr) volatile unsigned short name # define SFR16LEX(name, addr) volatile unsigned short name # define SFR32(name, fulladdr) volatile unsigned long name # define SFR32E(name, fulladdr) volatile unsigned long name #endif #endif //COMPILER_H
STC89XX.h
#ifndef STC89xx_H #define STC89xx_H #include "compiler.h" // 适用于 STC89xx / STC90xx 系列的芯片 // Modified based on STC-ISP version by: ZnHoCn /* The following is STC additional SFR*/ /* * #define _AUXR 0x8e * SFR(AUXR, 0x8e); * #define _AUXR1 0xa2 * SFR(AUXR1, 0xa2); * #define _IPH 0xb7 * SFR(IPH, 0xb7); */ #define _P4 0xe8 SFR(P4, 0xe8); SBIT(P46, _P4, 6); SBIT(P45, _P4, 5); //ISP下载需勾选"ALE脚用作P4.5口" SBIT(P44, _P4, 4); SBIT(P43, _P4, 3); SBIT(P42, _P4, 2); SBIT(P41, _P4, 1); SBIT(P40, _P4, 0); #define _XICON 0xc0 SFR(XICON, 0xc0); #define _WDT_CONTR 0xe1 SFR(WDT_CONTR, 0xe1); #define _ISP_DATA 0xe2 SFR(ISP_DATA, 0xe2); #define _ISP_ADDRH 0xe3 SFR(ISP_ADDRH, 0xe3); #define _ISP_ADDRL 0xe4 SFR(ISP_ADDRL, 0xe4); #define _ISP_CMD 0xe5 SFR(ISP_CMD, 0xe5); #define _ISP_TRIG 0xe6 SFR(ISP_TRIG, 0xe6); #define _ISP_CONTR 0xe7 SFR(ISP_CONTR, 0xe7); /* Above is STC additional SFR */ /*-------------------------------------------------------------------------- REG51F.H Header file for 8xC31/51, 80C51Fx, 80C51Rx+ Copyright (c) 1988-1999 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. Modification according to DataSheet from April 1999 - SFR's AUXR and AUXR1 added for 80C51Rx+ derivatives --------------------------------------------------------------------------*/ /* BYTE Registers */ #define _P0 0x80 SFR(P0, 0x80); SBIT(P00, _P0, 0); SBIT(P01, _P0, 1); SBIT(P02, _P0, 2); SBIT(P03, _P0, 3); SBIT(P04, _P0, 4); SBIT(P05, _P0, 5); SBIT(P06, _P0, 6); SBIT(P07, _P0, 7); #define _P1 0x90 SFR(P1, 0x90); SBIT(P10, _P1, 0); SBIT(P11, _P1, 1); SBIT(P12, _P1, 2); SBIT(P13, _P1, 3); SBIT(P14, _P1, 4); SBIT(P15, _P1, 5); SBIT(P16, _P1, 6); SBIT(P17, _P1, 7); #define _P2 0xA0 SFR(P2, 0xA0); SBIT(P20, _P2, 0); SBIT(P21, _P2, 1); SBIT(P22, _P2, 2); SBIT(P23, _P2, 3); SBIT(P24, _P2, 4); SBIT(P25, _P2, 5); SBIT(P26, _P2, 6); SBIT(P27, _P2, 7); #define _P3 0xB0 SFR(P3, 0xB0); SBIT(P30, _P3, 0); SBIT(P31, _P3, 1); SBIT(P32, _P3, 2); SBIT(P33, _P3, 3); SBIT(P34, _P3, 4); SBIT(P35, _P3, 5); SBIT(P36, _P3, 6); SBIT(P37, _P3, 7); #define _PSW 0xD0 SFR(PSW, 0xD0); #define _ACC 0xE0 SFR(ACC, 0xE0); #define _B 0xF0 SFR(B, 0xF0); #define _SP 0x81 SFR(SP, 0x81); #define _DPL 0x82 SFR(DPL, 0x82); #define _DPH 0x83 SFR(DPH, 0x83); #define _PCON 0x87 SFR(PCON, 0x87); #define _TCON 0x88 SFR(TCON, 0x88); #define _TMOD 0x89 SFR(TMOD, 0x89); #define _TL0 0x8A SFR(TL0, 0x8A); #define _TL1 0x8B SFR(TL1, 0x8B); #define _TH0 0x8C SFR(TH0, 0x8C); #define _TH1 0x8D SFR(TH1, 0x8D); #define _IE 0xA8 SFR(IE, 0xA8); #define _IP 0xB8 SFR(IP, 0xB8); #define _SCON 0x98 SFR(SCON, 0x98); #define _SBUF 0x99 SFR(SBUF, 0x99); /* 80C51Fx/Rx Extensions */ #define _AUXR 0x8E SFR(AUXR, 0x8E); #define _AUXR1 0xA2 SFR(AUXR1, 0xA2); #define _SADDR 0xA9 SFR(SADDR, 0xA9); #define _IPH 0xB7 SFR(IPH, 0xB7); #define _SADEN 0xB9 SFR(SADEN, 0xB9); #define _T2CON 0xC8 SFR(T2CON, 0xC8); #define _T2MOD 0xC9 SFR(T2MOD, 0xC9); #define _RCAP2L 0xCA SFR(RCAP2L, 0xCA); #define _RCAP2H 0xCB SFR(RCAP2H, 0xCB); #define _TL2 0xCC SFR(TL2, 0xCC); #define _TH2 0xCD SFR(TH2, 0xCD); /* PCA SFR #define _CCON 0xD8 SFR(CCON, 0xD8); #define _CMOD 0xD9 SFR(CMOD, 0xD9); #define _CCAPM0 0xDA SFR(CCAPM0, 0xDA); #define _CCAPM1 0xDB SFR(CCAPM1, 0xDB); #define _CCAPM2 0xDC SFR(CCAPM2, 0xDC); #define _CCAPM3 0xDD SFR(CCAPM3, 0xDD); #define _CCAPM4 0xDE SFR(CCAPM4, 0xDE); #define _CL 0xE9 SFR(CL, 0xE9); #define _CCAP0L 0xEA SFR(CCAP0L, 0xEA); #define _CCAP1L 0xEB SFR(CCAP1L, 0xEB); #define _CCAP2L 0xEC SFR(CCAP2L, 0xEC); #define _CCAP3L 0xED SFR(CCAP3L, 0xED); #define _CCAP4L 0xEE SFR(CCAP4L, 0xEE); #define _CH 0xF9 SFR(CH, 0xF9); #define _CCAP0H 0xFA SFR(CCAP0H, 0xFA); #define _CCAP1H 0xFB SFR(CCAP1H, 0xFB); #define _CCAP2H 0xFC SFR(CCAP2H, 0xFC); #define _CCAP3H 0xFD SFR(CCAP3H, 0xFD); #define _CCAP4H 0xFE SFR(CCAP4H, 0xFE); */ /* BIT Registers */ /* PSW */ SBIT(CY, _PSW, 7); SBIT(AC, _PSW, 6); SBIT(F0, _PSW, 5); SBIT(RS1, _PSW, 4); SBIT(RS0, _PSW, 3); SBIT(OV, _PSW, 2); SBIT(P, _PSW, 0); /* TCON */ SBIT(TF1, _TCON, 7); SBIT(TR1, _TCON, 6); SBIT(TF0, _TCON, 5); SBIT(TR0, _TCON, 4); SBIT(IE1, _TCON, 3); SBIT(IT1, _TCON, 2); SBIT(IE0, _TCON, 1); SBIT(IT0, _TCON, 0); /* IE */ SBIT(EA, _IE, 7); SBIT(EC, _IE, 6); SBIT(ET2, _IE, 5); SBIT(ES, _IE, 4); SBIT(ET1, _IE, 3); SBIT(EX1, _IE, 2); SBIT(ET0, _IE, 1); SBIT(EX0, _IE, 0); /* IP */ /* SBIT(PPC, _IP, 6);*/ SBIT(PT2, _IP, 5); SBIT(PS, _IP, 4); SBIT(PT1, _IP, 3); SBIT(PX1, _IP, 2); SBIT(PT0, _IP, 1); SBIT(PX0, _IP, 0); /* P3 */ SBIT(RD, _P3, 7); SBIT(WR, _P3, 6); SBIT(T1, _P3, 5); SBIT(T0, _P3, 4); SBIT(INT1, _P3, 3); SBIT(INT0, _P3, 2); SBIT(TXD, _P3, 1); SBIT(RXD, _P3, 0); /* SCON */ SBIT(SM0, _SCON, 7); // alternatively "FE" SBIT(FE, _SCON, 7); SBIT(SM1, _SCON, 6); SBIT(SM2, _SCON, 5); SBIT(REN, _SCON, 4); SBIT(TB8, _SCON, 3); SBIT(RB8, _SCON, 2); SBIT(TI, _SCON, 1); SBIT(RI, _SCON, 0); /* P1 */ /* PCA SBIT(CEX4, _P1, 7); SBIT(CEX3, _P1, 6); SBIT(CEX2, _P1, 5); SBIT(CEX1, _P1, 4); SBIT(CEX0, _P1, 3); SBIT(ECI, _P1, 2); */ SBIT(T2EX, _P1, 1); SBIT(T2, _P1, 0); /* T2CON */ SBIT(TF2, _T2CON, 7); SBIT(EXF2, _T2CON, 6); SBIT(RCLK, _T2CON, 5); SBIT(TCLK, _T2CON, 4); SBIT(EXEN2, _T2CON, 3); SBIT(TR2, _T2CON, 2); SBIT(C_T2, _T2CON, 1); SBIT(CP_RL2, _T2CON, 0); /* CCON */ /* PCA SBIT(CF, _CCON, 7); SBIT(CR, _CCON, 6); SBIT(CCF4, _CCON, 4); SBIT(CCF3, _CCON, 3); SBIT(CCF2, _CCON, 2); SBIT(CCF1, _CCON, 1); SBIT(CCF0, _CCON, 0); */ #endif
参考链接:
https://www.bilibili.com/read/cv18942590
https://blog.csdn.net/weixin_44681954/article/details/123095837
(/ω\)扁担真厉害
抓住( ๑´•ω•) “(ㆆᴗㆆ)