当前位置:网站首页>Sdcc compiler + vscode to develop 8-bit microcontroller
Sdcc compiler + vscode to develop 8-bit microcontroller
2022-06-21 12:05:00 【Summer foam and light rain】
Write it at the front :
The purpose of this article is to summarize backup 、 For future reference , Because it's a personal summary , If there is any wrong , Welcome to correct ; in addition , Most of the content comes from the Internet 、 Books 、 And all kinds of manuals , In case of infringement, please inform , Immediately delete the post and apologize .
SDCC It's a small device C Language compiler , The compiler supports standard C Language ; be relative to GCC The compiler may not be well known , But it follows GCC equally , It's cross platform , And follow GPL Open source licenses . This experiment uses nuvoton Of MS51 Series single chip microcomputer to operate ( be based on 8051 kernel )
sdcc Official website :http://sdcc.sourceforge.net/
Wiki Home page :https://sourceforge.net/p/sdcc/wiki/Home/
Catalog
- One 、 About SDCC
- Two 、 Installation and environment configuration
- 3、 ... and 、SDCC The rules ( Only for MCS51 explain )
- Four 、SDCC Header file processing
- 5、 ... and 、 Engineering construction
- 6、 ... and 、VSCode Grammatical modification
- 7、 ... and 、Makefile Procedural management
- 8、 ... and 、 Program compilation
- Nine 、 summary
- Ten 、 Related links
One 、 About SDCC
SDCC Is retargetable 、 The standard of optimization C(ANSI C89,ISO C99,ISO C11) Compiler Suite , The target is based on Intel MCS51 Microprocessor of (8031、8032、8051、8052 etc. ),Maxim( It used to be Dallas )DS80C390 variant , Freescale ( be based on HC08(hc08,s08), be based on Zilog Z80 Of MCU(z80,z180,gbz80,Rabbit 2000/3000,Rabbit 3000A,TLCS-90),Padauk(pdk14,pdk15) and STMicroelectronics STM8.
Installed on SDCC after , You can see the supported device types by viewing the version number of the instruction :

then , Here's a post for discussion SDCC Some of the related things , And it's like ( I'm not sure )SDCC The developers of are also in it , You can have a look at what you are interested in :https://wap.newsmth.net/article/905eb27dddf829f15c81077215d66284?title=%E7%94%B5%E8%B7%AF%E8%AE%BE%E8%AE%A1%E4%B8%8E%E8%B0%83%E8%AF%95&from=search
SDCC More in Keil Come on , It's right C The rigor of grammar is very high , More like a standard C Language compiler , It's not like Keil Put some... Like that warning Remove , Automatically help you optimize ; I said before. , SDCC Is a good compiler , The optimization is a little imperfect , So that the volume of code generation is still larger than Keil C51 Bigger ( Do I still have some optimization instructions get Here we are ?).
Two 、 Installation and environment configuration
1、 SDCC
The download path of the software is in the above sdcc There are corresponding interfaces on the home page , Just download the relevant platform packages and install them , Add the system environment variables after the installation is completed, which is needless to say , In the end sdcc -v Test and inspection . It's that simple ...
2、 MinGW-w64
Download address :https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/
After installation, you need to add system environment variables , You can use cmd command :gcc -v test .
3、MSYS2 perhaps Git( Just support shell Command the terminal console on the line )
msys2 download <-- Self stamping
Git Search and download by yourself .
2、 VSCode
VSCode Environment deployment can be seen from the previous STM32 Development of VS Code + gcc Environment compilation The third section of , Then if you know how to configure VSCode Configuration item of , Then you can skip the following configuration operations and write it yourself .
c_cpp_properties.json
{ "configurations": [ { "name": "C51", "includePath": [ // Store... In your project include Folder path for "${workspaceFolder}/**", "${workspaceFolder}/App", "${workspaceFolder}/Libraries/Device/Include", "${workspaceFolder}/Libraries/StdDriver/inc" ], "defines": [ "_DEBUG", "UNICODE", "_UNICODE", ], "compilerPath": "C:\\Program Files\\SDCC\\bin\\sdcc.exe", // sdcc bin route "cStandard": "gnu18", "cppStandard": "gnu++14", "intelliSenseMode": "gcc-x64" } ], "version": 4 }tasks.json
{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "label": "Build", "type": "shell", "command": "make", "args": [ "target=${fileBasenameNoExtension}" ], "group": { "kind": "build", "isDefault": true } } ] }settings.json
{ "files.encoding": "gb2312", "files.autoGuessEncoding": true, "C_Cpp.errorSquiggles": "Enabled", // Grammar mistakes "files.associations": { "main.h": "c", }, /* Terminal in Windows The use of shell The path of */ "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe", }
3、 ... and 、SDCC The rules ( Only for MCS51 explain )
1、 Supported data types

2、 Storage type

be relative to Keil, Its storage type keyword is prefixed with ’ __ ’ Double underline , This is also SDCC Unique style .
__data : This is the default for small memory mode ( Universal ) address space , The declared variables will be placed in 8051 Direct addressing of the kernel RAM in .
__idata : The variables in this address space will be assigned to 8051 Internal RAM The indirectly addressable part of .
__pdata : Storage type pdata External data storage for accessing paging .
__xdata : The variables in this address space will be placed externally RAM in .
__code : Memory address space for storing program code .
3、 Memory mode
SDCC Four memory modes are supported :(small, medium, large, huge)
use SDCC Compile time , The default is small mode . If you want to force SDCC Use a specific memory mode , You can use the following command line arguments ( In the manual P3.3.6 Chapters can be queried ):

Be similar to Keil This option of ( It's just Keil yes GUI operation ,SDCC It is a command operation ):

The storage location of variables in different modes is different , You can refer to the manual P3.13 chapter ; in general , For the middle (medium)、 Big (large)、 huge (huge) Storage mode , All variables declared without specifying an internal named address space will be assigned to the external RAM in , This includes all parameters and local variables ( For non reentrant functions ), Medium mode uses pdata, Large mode uses xdata; Small memory mode (small) It is stored in by default data.
4、bit and sbit keyword
bit and int、char Or something like that , It's just char = 8 position ,bit = 1 position ;
sbit Is a bit corresponding to a bit addressable space .
alike , stay SDCC The prefix is added here ’ __ ’ Double underline , become __bit、__sbit
5、SFR( special function register )
And bit Keyword similar , Represents a named address space , Used to describe 8051 Special function registers and special bit variables .
eg:
__sfr __at (0x80) P0; /* special function register P0 at location 0x80 */
6、 Absolute addressing
SDCC Support the adoption of __at Keyword indicates absolute addressing .
7、 Built in assembly
SDCC Fully supports inline assembly . When using this function , Assembly code should be embedded in __asm and __endasm Between identifiers .
8、 Compile build file
- xxx.asm: Assembly file of program .
- xxx.lst: Program list file .
- xxx.rst: List file updated by linker .
- xxx.sym: The list of symbols generated by the linker .
- xxx.rel: Object files generated by the assembler , Provide for linker to use .
- xxx.map: The final memory map updated by the linker .
- xxx.mem: Summary of memory usage .
- xxx.ihx:Intel Loading module in hexadecimal format . This file must be downloaded to the microcontroller .
Four 、SDCC Header file processing
I said before. ,sdcc The non-standard keyword of is with ‘ __ ’ Double slide line , however MS51 The official SDK In bag , Register addressing keywords are all keil Format , This needs to be converted ; If it is some mature 8051 The core of MCU , Then you can go to sdcc Installation path for …\SDCC\include\mcs51 Find the corresponding chip header file , If it were not so , Then you have to convert the format yourself .sdcc format conversion , You can search the Internet , Here's a link :https://www.amobbs.com/thread-5625040-1-1.html, There is a conversion tool inside , Of course, you can also write a program by yourself .

5、 ... and 、 Engineering construction
Because it's using VSCode Do editorial development , As long as there is .vscode The configuration item of the folder is OK , The rest of the compilation process is left to sdcc compile , Therefore, the construction of the project is relatively simple , Folder creation and migration SDK Libraries are convenient , The following is my project file distribution ( It seems easy to understand ):

here Libraries The contents of the folder are directly migrated SDK Library , For the rest, you can see the purpose by looking at the file name .
The other is ,App Folder , except lint.h( Used for parsing mcs51 Specific code ) And added main.h The header file ( Usual main The master file is not the lead file ); Then why these two , To avoid VSCode The grammar of is wrong , Of course you can do it once and for all , Just turn it off VSCode Syntax tips for ( This can be seen from the above settings.json The configuration file ), as for lint.h It's from sdcc Installation path for …\SDCC\include\mcs51 extracted , Original flavor .
6、 ... and 、VSCode Grammatical modification
It also says ,sdcc Some non ASCII C keyword , therefore VSCode Will highlight syntax errors in the program ; that , Let's solve this problem ( Of course , Instead of checking this crude form with closing Syntax ):
1、 The first thing to understand is , In the use of sdcc When compiling , Yes, it will be automatically predefined before compilation __SDCC broad , This makes it easy to do , Compile... With conditions , Distinguish the intelligent prompt running environment from SDCC Actual compilation environment , Use an empty one define To replace these keywords , Registers are also replaced by macros , And then in SDCC The original... Is called during actual compilation C51 Register definition of syntax .
2、 According to the first point above , Then combine the above mentioned lint.h( The default is to leave sdcc Empty keyword define), Get such an example :
#ifdef __SDCC
__sfr __at (0x80) P0; // Actually valid register definitions
#else
/* Keyword section */
#define __sfr // Empty keyword macro , Eliminate keyword incompatibility ( stay lint.h You can get relevant keywords on )
...
...
/* Register section */
#define P0 (*(char *) (0x80)) // No practical significance , For compatibility ( cheating ) standard C Register symbol of syntax
...
...
#endif
Compile through the above conditions , The code can be divided into two environments: intelligent prompt and actual compilation :
- At actual compilation time ,SDCC The compiler predefines
__SDCCmacro , Therefore, the actually valid register definitions are used in the actual compilation ; - In the intelligent prompt environment , Replace all keywords with empty macros , Eliminate keyword incompatibility , Then a macro is used to define the register , Ensure that the register name smart prompt can still be used . Here, the register is defined as char* Pointer dereference lvalue expression , The purpose is to cater to the fact that it is legal to assign a value to a register grammatically , The value in parentheses can be any value , It doesn't make much sense , Of course, it is more appropriate to use the original value of the register , But it's more troublesome to deal with .
3、 Right up there 1、2 To sum up , You can get :
#ifndef __MAIN_H__
#define __MAIN_H__
#include <stdint.h>
#ifdef __SDCC
#include "MS51_16K.h" // hold keil After format conversion sdcc Register header file
#else
#include <stdbool.h> // lint. You need to use... In the file bool Keyword definition
#include "lint.h" // Keyword handling
#include "SFR_Macro_MS51_16K.h"
/******************************************************************************/
/* Macro define header files */
/******************************************************************************/
#define P0 (*(char *) (0)) //= 0x80;
#define SP (*(char *) (0)) //= 0x81;
#define DPL (*(char *) (0)) //= 0x82;
#define DPH (*(char *) (0)) //= 0x83;
#define RCTRIM0 (*(char *) (0)) //= 0x84;
#define RCTRIM1 (*(char *) (0)) //= 0x85;
#define RWK (*(char *) (0)) //= 0x86;
#define PCON (*(char *) (0)) //= 0x87;
#define TCON (*(char *) (0)) //= 0x88;
#define TMOD (*(char *) (0)) //= 0x89;
#define TL0 (*(char *) (0)) //= 0x8A;
#define TL1 (*(char *) (0)) //= 0x8B;
#define TH0 (*(char *) (0)) //= 0x8C;
#define TH1 (*(char *) (0)) //= 0x8D;
#define CKCON (*(char *) (0)) //= 0x8E;
#define WKCON (*(char *) (0)) //= 0x8F;
#define P1 (*(char *) (0)) //= 0x90;
#define SFRS (*(char *) (0)) //= 0x91; //TA Protection
#define CAPCON0 (*(char *) (0)) //= 0x92;
#define CAPCON1 (*(char *) (0)) //= 0x93;
#define CAPCON2 (*(char *) (0)) //= 0x94;
#define CKDIV (*(char *) (0)) //= 0x95;
#define CKSWT (*(char *) (0)) //= 0x96; //TA Protection
#define CKEN (*(char *) (0)) //= 0x97; //TA Protection
#define SCON (*(char *) (0)) //= 0x98;
#define SBUF (*(char *) (0)) //= 0x99;
#define SBUF_1 (*(char *) (0)) //= 0x9A;
#define EIE (*(char *) (0)) //= 0x9B;
#define EIE1 (*(char *) (0)) //= 0x9C;
#define CHPCON (*(char *) (0)) //= 0x9F; //TA Protection
#define P2 (*(char *) (0)) //= 0xA0;
#define AUXR1 (*(char *) (0)) //= 0xA2;
#define BODCON0 (*(char *) (0)) //= 0xA3; //TA Protection
#define IAPTRG (*(char *) (0)) //= 0xA4; //TA Protection
#define IAPUEN (*(char *) (0)) //= 0xA5; //TA Protection
#define IAPAL (*(char *) (0)) //= 0xA6;
#define IAPAH (*(char *) (0)) //= 0xA7;
#define IE (*(char *) (0)) //= 0xA8;
#define SADDR (*(char *) (0)) //= 0xA9;
#define WDCON (*(char *) (0)) //= 0xAA; //TA Protection
#define BODCON1 (*(char *) (0)) //= 0xAB; //TA Protection
#define P3M1 (*(char *) (0)) //= 0xAC;
#define P3S (*(char *) (0)) //= 0xAC; //Page1
#define P3M2 (*(char *) (0)) //= 0xAD;
#define P3SR (*(char *) (0)) //= 0xAD; //Page1
#define IAPFD (*(char *) (0)) //= 0xAE;
#define IAPCN (*(char *) (0)) //= 0xAF;
#define P3 (*(char *) (0)) //= 0xB0;
#define P0M1 (*(char *) (0)) //= 0xB1;
#define P0S (*(char *) (0)) //= 0xB1; //Page1
#define P0M2 (*(char *) (0)) //= 0xB2;
#define P0SR (*(char *) (0)) //= 0xB2; //Page1
#define P1M1 (*(char *) (0)) //= 0xB3;
#define P1S (*(char *) (0)) //= 0xB3; //Page1
#define P1M2 (*(char *) (0)) //= 0xB4;
#define P1SR (*(char *) (0)) //= 0xB4; //Page1
#define P2S (*(char *) (0)) //= 0xB5;
#define IPH (*(char *) (0)) //= 0xB7;
#define PWMINTC (*(char *) (0)) //= 0xB7; //Page1
#define IP (*(char *) (0)) //= 0xB8;
#define SADEN (*(char *) (0)) //= 0xB9;
#define SADEN_1 (*(char *) (0)) //= 0xBA;
#define SADDR_1 (*(char *) (0)) //= 0xBB;
#define I2DAT (*(char *) (0)) //= 0xBC;
#define I2STAT (*(char *) (0)) //= 0xBD;
#define I2CLK (*(char *) (0)) //= 0xBE;
#define I2TOC (*(char *) (0)) //= 0xBF;
#define I2CON (*(char *) (0)) //= 0xC0;
#define I2ADDR (*(char *) (0)) //= 0xC1;
#define ADCRL (*(char *) (0)) //= 0xC2;
#define ADCRH (*(char *) (0)) //= 0xC3;
#define T3CON (*(char *) (0)) //= 0xC4;
#define PWM4H (*(char *) (0)) //= 0xC4; //Page1
#define RL3 (*(char *) (0)) //= 0xC5;
#define PWM5H (*(char *) (0)) //= 0xC5; //Page1
#define RH3 (*(char *) (0)) //= 0xC6;
#define PIOCON1 (*(char *) (0)) //= 0xC6; //Page1
#define TA (*(char *) (0)) //= 0xC7;
#define T2CON (*(char *) (0)) //= 0xC8;
#define T2MOD (*(char *) (0)) //= 0xC9;
#define RCMP2L (*(char *) (0)) //= 0xCA;
#define RCMP2H (*(char *) (0)) //= 0xCB;
#define TL2 (*(char *) (0)) //= 0xCC;
#define PWM4L (*(char *) (0)) //= 0xCC; //Page1
#define TH2 (*(char *) (0)) //= 0xCD;
#define PWM5L (*(char *) (0)) //= 0xCD; //Page1
#define ADCMPL (*(char *) (0)) //= 0xCE;
#define ADCMPH (*(char *) (0)) //= 0xCF;
#define PSW (*(char *) (0)) //= 0xD0;
#define PWMPH (*(char *) (0)) //= 0xD1;
#define PWM0H (*(char *) (0)) //= 0xD2;
#define PWM1H (*(char *) (0)) //= 0xD3;
#define PWM2H (*(char *) (0)) //= 0xD4;
#define PWM3H (*(char *) (0)) //= 0xD5;
#define PNP (*(char *) (0)) //= 0xD6;
#define FBD (*(char *) (0)) //= 0xD7;
#define PWMCON0 (*(char *) (0)) //= 0xD8;
#define PWMPL (*(char *) (0)) //= 0xD9;
#define PWM0L (*(char *) (0)) //= 0xDA;
#define PWM1L (*(char *) (0)) //= 0xDB;
#define PWM2L (*(char *) (0)) //= 0xDC;
#define PWM3L (*(char *) (0)) //= 0xDD;
#define PIOCON0 (*(char *) (0)) //= 0xDE;
#define PWMCON1 (*(char *) (0)) //= 0xDF;
#define ACC (*(char *) (0)) //= 0xE0;
#define ADCCON1 (*(char *) (0)) //= 0xE1;
#define ADCCON2 (*(char *) (0)) //= 0xE2;
#define ADCDLY (*(char *) (0)) //= 0xE3;
#define C0L (*(char *) (0)) //= 0xE4;
#define C0H (*(char *) (0)) //= 0xE5;
#define C1L (*(char *) (0)) //= 0xE6;
#define C1H (*(char *) (0)) //= 0xE7;
#define ADCCON0 (*(char *) (0)) //= 0xE8;
#define PICON (*(char *) (0)) //= 0xE9;
#define PINEN (*(char *) (0)) //= 0xEA;
#define PIPEN (*(char *) (0)) //= 0xEB;
#define PIF (*(char *) (0)) //= 0xEC;
#define C2L (*(char *) (0)) //= 0xED;
#define C2H (*(char *) (0)) //= 0xEE;
#define EIP (*(char *) (0)) //= 0xEF;
#define B (*(char *) (0)) //= 0xF0;
#define CAPCON3 (*(char *) (0)) //= 0xF1;
#define CAPCON4 (*(char *) (0)) //= 0xF2;
#define SPCR (*(char *) (0)) //= 0xF3;
#define SPCR2 (*(char *) (0)) //= 0xF3; //Page1
#define SPSR (*(char *) (0)) //= 0xF4;
#define SPDR (*(char *) (0)) //= 0xF5;
#define AINDIDS (*(char *) (0)) //= 0xF6;
#define EIPH (*(char *) (0)) //= 0xF7;
#define SCON_1 (*(char *) (0)) //= 0xF8;
#define PDTEN (*(char *) (0)) //= 0xF9; //TA Protection
#define PDTCNT (*(char *) (0)) //= 0xFA; //TA Protection
#define PMEN (*(char *) (0)) //= 0xFB;
#define PMD (*(char *) (0)) //= 0xFC;
#define EIP1 (*(char *) (0)) //= 0xFE;
#define EIPH1 (*(char *) (0)) //= 0xFF;
/* BIT Registers */
/* SCON_1 */
#define SM0_1 (*(char *) (0)) //= SCON_1^7;
#define FE_1 (*(char *) (0)) //= SCON_1^7;
#define SM1_1 (*(char *) (0)) //= SCON_1^6;
#define SM2_1 (*(char *) (0)) //= SCON_1^5;
#define REN_1 (*(char *) (0)) //= SCON_1^4;
#define TB8_1 (*(char *) (0)) //= SCON_1^3;
#define RB8_1 (*(char *) (0)) //= SCON_1^2;
#define TI_1 (*(char *) (0)) //= SCON_1^1;
#define RI_1 (*(char *) (0)) //= SCON_1^0;
/* ADCCON0 */
#define ADCF (*(char *) (0)) //= ADCCON0^7;
#define ADCS (*(char *) (0)) //= ADCCON0^6;
#define ETGSEL1 (*(char *) (0)) //= ADCCON0^5;
#define ETGSEL0 (*(char *) (0)) //= ADCCON0^4;
#define ADCHS3 (*(char *) (0)) //= ADCCON0^3;
#define ADCHS2 (*(char *) (0)) //= ADCCON0^2;
#define ADCHS1 (*(char *) (0)) //= ADCCON0^1;
#define ADCHS0 (*(char *) (0)) //= ADCCON0^0;
/* PWMCON0 */
#define PWMRUN (*(char *) (0)) //= PWMCON0^7;
#define LOAD (*(char *) (0)) //= PWMCON0^6;
#define PWMF (*(char *) (0)) //= PWMCON0^5;
#define CLRPWM (*(char *) (0)) //= PWMCON0^4;
/* PSW */
#define CY (*(char *) (0)) //= PSW^7;
#define AC (*(char *) (0)) //= PSW^6;
#define F0 (*(char *) (0)) //= PSW^5;
#define RS1 (*(char *) (0)) //= PSW^4;
#define RS0 (*(char *) (0)) //= PSW^3;
#define OV (*(char *) (0)) //= PSW^2;
#define P (*(char *) (0)) //= PSW^0;
/* T2CON */
#define TF2 (*(char *) (0)) //= T2CON^7;
#define TR2 (*(char *) (0)) //= T2CON^2;
#define CM_RL2 (*(char *) (0)) //= T2CON^0;
/* I2CON */
#define I2CEN (*(char *) (0)) //= I2CON^6;
#define STA (*(char *) (0)) //= I2CON^5;
#define STO (*(char *) (0)) //= I2CON^4;
#define SI (*(char *) (0)) //= I2CON^3;
#define AA (*(char *) (0)) //= I2CON^2;
#define I2CPX (*(char *) (0)) //= I2CON^0;
/* IP */
#define PADC (*(char *) (0)) //= IP^6;
#define PBOD (*(char *) (0)) //= IP^5;
#define PS (*(char *) (0)) //= IP^4;
#define PT1 (*(char *) (0)) //= IP^3;
#define PX1 (*(char *) (0)) //= IP^2;
#define PT0 (*(char *) (0)) //= IP^1;
#define PX0 (*(char *) (0)) //= IP^0;
/* P3 */
#define P30 (*(char *) (0)) //= P3^0;
/* IE */
#define EA (*(char *) (0)) //= IE^7;
#define EADC (*(char *) (0)) //= IE^6;
#define EBOD (*(char *) (0)) //= IE^5;
#define ES (*(char *) (0)) //= IE^4;
#define ET1 (*(char *) (0)) //= IE^3;
#define EX1 (*(char *) (0)) //= IE^2;
#define ET0 (*(char *) (0)) //= IE^1;
#define EX0 (*(char *) (0)) //= IE^0;
/* P2 */
#define P20 (*(char *) (0)) //= P2^0;
/* SCON */
#define SM0 (*(char *) (0)) //= SCON^7;
#define FE (*(char *) (0)) //= SCON^7;
#define SM1 (*(char *) (0)) //= SCON^6;
#define SM2 (*(char *) (0)) //= SCON^5;
#define REN (*(char *) (0)) //= SCON^4;
#define TB8 (*(char *) (0)) //= SCON^3;
#define RB8 (*(char *) (0)) //= SCON^2;
#define TI (*(char *) (0)) //= SCON^1;
#define RI (*(char *) (0)) //= SCON^0;
/* P1 */
#define P17 (*(char *) (0)) //= P1^7;
#define P16 (*(char *) (0)) //= P1^6;
#define TXD_1 (*(char *) (0)) //= P1^6;
#define P15 (*(char *) (0)) //= P1^5;
#define P14 (*(char *) (0)) //= P1^4;
#define SDA (*(char *) (0)) //= P1^4;
#define P13 (*(char *) (0)) //= P1^3;
#define SCL (*(char *) (0)) //= P1^3;
#define P12 (*(char *) (0)) //= P1^2;
#define P11 (*(char *) (0)) //= P1^1;
#define P10 (*(char *) (0)) //= P1^0;
/* TCON */
#define TF1 (*(char *) (0)) //= TCON^7;
#define TR1 (*(char *) (0)) //= TCON^6;
#define TF0 (*(char *) (0)) //= TCON^5;
#define TR0 (*(char *) (0)) //= TCON^4;
#define IE1 (*(char *) (0)) //= TCON^3;
#define IT1 (*(char *) (0)) //= TCON^2;
#define IE0 (*(char *) (0)) //= TCON^1;
#define IT0 (*(char *) (0)) //= TCON^0;
/* P0 */
#define P07 (*(char *) (0)) //= P0^7;
#define RXD (*(char *) (0)) //= P0^7;
#define P06 (*(char *) (0)) //= P0^6;
#define TXD (*(char *) (0)) //= P0^6;
#define P05 (*(char *) (0)) //= P0^5;
#define P04 (*(char *) (0)) //= P0^4;
#define STADC (*(char *) (0)) //= P0^4;
#define P03 (*(char *) (0)) //= P0^3;
#define P02 (*(char *) (0)) //= P0^2;
#define RXD_1 (*(char *) (0)) //= P0^2;
#define P01 (*(char *) (0)) //= P0^1;
#define MISO (*(char *) (0)) //= P0^1;
#define P00 (*(char *) (0)) //= P0^0;
#define MOSI (*(char *) (0)) //= P0^0;
#endif /* __SDCC */
#endif /* __MAIN_H__ */
For register definition processing , Can directly copy The original keil Format include The contents of the document , Then directly put the keyword sfr、sbit Replace with #define , And then = Replace with (*(char *) (0)) //= So you , Isn't it very nice.
7、 ... and 、Makefile Procedural management
SDCC It is not supported to compile multiple source code files at the same time , Therefore, the compilation of multi file projects needs to be carried out step by step . Suppose your project contains foo1.cfoo2.cmain.c Three files , The compilation process is as follows :
sdcc -c foo1.c
sdcc -c foo2.c
sdcc main.c foo1.rel foo2.rel
You can also compile in the following way :
sdcc -c main.c
sdcc main.rel foo1.rel foo2.rel
It is worth mentioning that ,sdcc And gcc The command support of is a little different , But most of them are compatible , So what commands are supported , You need to look through sdcc Manuals .
For multi file projects, it's best to write one Makefile File to maintain or write a bat Batch file . Here is what I used directly Makefile Document bar , Analyze something , You can see the previous Links :https://blog.csdn.net/qq_42992084/article/details/95893283; If you are Linux user , You should be very clear about these commands , If you guys know more , Please also comment in the comments section :
######################################
# target path
######################################
TARGET = MS51FB
#######################################
# Build path
#######################################
BUILD_DIR = build
######################################
# source
######################################
SRCDIR = App
LIB_SRC = #Libraries/StdDriver/src
USER_SRC = source#/bsp.c \
source/bsp_time.c \
source/bsp_uart.c
# C sources
C_SOURCES := $(wildcard $(SRCDIR)/*.c $(LIB_SRC)/*.c)
C_SOURCES += $(wildcard $(USER_SRC)/*.c)
ASM_SOURCES = $(wildcard $(SRCDIR)/*.asm)
C_SRC_FILE = $(notdir $(C_SOURCES))
C_OBJ_FILE = $(C_SRC_FILE:%.c=%.c.rel)
ASM_SRC_FILE = $(notdir $(ASM_SOURCES))
ASM_OBJ_FILE = $(ASM_SRC_FILE:%.asm=%.asm.rel)
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# optimization
OPT =
#######################################
# cross compile
#######################################
PREFIX =
CC = $(PREFIX)sdcc
AS = $(PREFIX)sdas8051
MCU_MODEL = -mmcs51
RM = -rm -rf
MAKE = make
# ------------------------------------------------------
# Usually SDCC's small memory model is the best choice. If
# you run out of internal RAM, you will need to declare
# variables as "xdata", or switch to larger model
# Memory Model (small, medium, large, huge)
MODEL = --model-small
# ------------------------------------------------------
# Memory Layout
# PRG Size = 4K Bytes
#CODE_SIZE = --code-loc 0x0000 --code-size 18432
CODE_SIZE = --code-size 18432
# INT-MEM Size = 256 Bytes
#IRAM_SIZE = --idata-loc 0x0000 --iram-size 256
IRAM_SIZE = --iram-size 256
# EXT-MEM Size = 4K Bytes
#XRAM_SIZE = --xram-loc 0x0000 --xram-size 768
XRAM_SIZE = --xram-size 768
# ------------------------------------------------------
#######################################
# FLAGS
#######################################
# macros for gcc
# AS defines
AS_DEFS =
# C defines
C_DEFS =
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = \
-IApp \
-ILibraries/Device/Include \
-ILibraries/StdDriver/inc \
-Iinclude
# libraries
LIBS =
LIBDIR =
# compile gcc flags
ASFLAGS = -l -s
CFLAGS = $(MCU_MODEL) $(C_DEFS) $(C_INCLUDES) $(MODEL) --out-fmt-ihx --no-xinit-opt --peep-file tools/peep.def
ifeq ($(DEBUG), 1)
CFLAGS +=
else
CFLAGS += $(OPT)
endif
#######################################
# LDFLAGS
#######################################
LDFLAGS = $(LIBDIR) $(LIBS) $(MCU_MODEL) $(MODEL) $(CODE_SIZE) $(IRAM_SIZE) $(XRAM_SIZE) --out-fmt-ihx
# default action: build all
.PHONY: all
all: $(BUILD_DIR)/$(TARGET).hex
#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(C_OBJ_FILE))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(ASM_OBJ_FILE))
$(BUILD_DIR)/%.c.rel: $(USER_SRC)/%.c
$(CC) -o [email protected] $(CFLAGS) -c $^
$(BUILD_DIR)/%.c.rel: $(LIB_SRC)/%.c
$(CC) -o [email protected] $(CFLAGS) -c $^
$(BUILD_DIR)/%.c.rel: $(SRCDIR)/%.c
$(CC) -o [email protected] $(CFLAGS) -c $^
$(BUILD_DIR)/%.asm.rel: $(SRCDIR)/%.asm
$(AS) $(ASFLAGS) -o [email protected] $^
$(BUILD_DIR)/%.ihx: $(OBJECTS)
$(CC) -o [email protected] $(LDFLAGS) $^
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.ihx | $(BUILD_DIR)
packihx $^ > [email protected]
$(BUILD_DIR):
mkdir [email protected]
#######################################
# clean up
#######################################
.PHONY: clean
clean:
$(RM)$(BUILD_DIR)/*
#######################################
# build asm
#######################################
HEADER_FILE = MS51_16K.h
HEADER_PATH = App
disasm: $(BUILD_DIR)/$(TARGET).hex
./tools/mcs51-disasm.pl -M $(HEADER_FILE) -I $(HEADER_PATH) -fl -rj -as $(BUILD_DIR)/$(TARGET).hex > $(BUILD_DIR)/$(TARGET).a51
# *** EOF ***
Here's to say ,sdcc Peculiar packihx Commands are used to generate Intel HEX Of documents ;mkdir Command in sdcc China does not support , You can delete him , Because of this , So keep it build Folder to store compiled files , If you delete it , Execution will go wrong ; perform disasm Command requires tool chain mcs51-disasm.pl Support for , Its description is as follows :

; in addition ,+= It seems that adding a single file is not supported , see USER_SRC It's about , Only through wildcard Scan add ... I don't know why , I hope the boss can answer one or two .
8、 ... and 、 Program compilation
#include "main.h"
#include "bsp.h"
#include "bsp_uart.h"
#include "bsp_time.h"
#include "bsp_eeprom.h"
#include "bsp_adc.h"
#include "bsp_pwm.h"
#include "bsp_wdt.h"
__bit BIT_TMP; //EA The staging ( Corresponding to the official database )
#define ENABLE_WDT 1
/* ISR Interrupt function prototype declaration ( See the manual for the reasons P3.8 chapter ) */
void UART0_ISR(void) __interrupt (4);
void Timer3_ISR(void) __interrupt (16);
/************************************************ The name of the function : System_Start work can : System initialization ginseng Count : nothing return return value : nothing *************************************************/
void System_Start(void)
{
clr_EA;
Bsp_Init();
UART0_Timer1_Init();
Timer3_Init(TIME_DIV16, 15000); // 10ms
// Timer0_Init();
// ADC_Config();
// PWM0_Init();
#if ENABLE_WDT
WDT_Init();
#endif /* ENABLE_WDT */
set_EA;
}
/************************************************ The name of the function : main work can : Main function entry ginseng Count : nothing return return value : int *************************************************/
int main(void)
{
uint16_t i = 0;
System_Start();
P12_QUASI_MODE;
P12 = 1;
for(i=0; i<3; i++)
{
P12 ^= 1;
SoftwareDelay_ms(0xFF);
}
#if ENABLE_WDT
WDT_EnableOpen();
#else
WDT_DisableClose();
#endif /* ENABLE_WDT */
while(1)
{
#if ENABLE_WDT
WDT_ReloadCounter();
#endif /* ENABLE_WDT */
printf_small("\n Hello world!");
SoftwareDelay_ms(0xFF);
}
}
/*---------------------------- END OF FILE ----------------------------*/
then make compile , Final output ( Success is displayed in the box ):

Download it in , You can see that Hello world! In the endless printout :
ad locum , The following points need to be noted :
1、 The interrupt function must be in main Function file ISR Prototype , Otherwise, there will be no interruption . Please refer to the manual for details P3.8 chapter . The following is an excerpt from some of the explanations :

2、 commonly , We are C The printout in the program is called printf Statement , But in sdcc On , It is recommended to use printf_small Output , Because for 8 Bit micro control says , Resources are scarce , Use printf_small It can meet the general output requirements , Of course, the above is limited to output integer and character variables ; For floating point variables , You need to compile the program with special instructions to get the output effect , See the manual for specific explanations P3.14.1 chapter .
3、 If using bin The file is burned onto the chip , It can be used sdcc Self contained makebin.exe Command line tools for conversion ( However, the converted file is relatively large ), The path can be in …\SDCC\bin Find below , By the following command :makebin xxx.ihx > xxx.bin
Or make use of hex2bin, Download address :https://sourceforge.net/projects/hex2bin/files/latest/download, This command is :hex2bin xxx.hex > xxx.bin
Makefile Under the bin File generation command :

In contrast , Because the former is filled with the remaining space , So the converted file is relatively large , Individuals are more inclined to the latter .
Nine 、 summary
1、 Out of commission double data type , Otherwise, the report will be wrong .
2、make Compilation can only compile all source files of the corresponding folder according to the law , You cannot choose to compile the corresponding source file .
3、 The interrupt function here is to be in main Prototype declaration at the file where the function is located , Otherwise, you cannot enter the interrupt program , The reason for not declaring is that it is useless to load the vector address of the interrupt function into the execution file .
4、sdcc The keywords used are the following keilC51 There are different keywords ; For some non ANSI C Key words of ,SDCC Both are defined in the way of starting with a double sliding line , Specific to see sdcc manual .
5、sdcc Supported command line commands , It's the same as what we usually use gcc Command line commands are different , Look at the details sdcc manual .
6、 Generally, the serial port is reset backward , It's using printf Output function , But in sdcc Use... In the compiler printf_small This function replaces .
7、sdcc When compiling a file , It will compile the unused code , So if space is tight , It is recommended to comment out some irrelevant code , Avoid code space bloat .
Ten 、 Related links
8051 C Development Using SDCC(Small Device C Compiler)
New Tang N76E003 8051 1T Single chip microcomputer pit entry record
SDCC Compiler concise tutorial
Use free SDCC C Compiler development DS89C430/450 Series microcontroller firmware
Use Visual Studio Code + CMake + SDCC Conduct C51 An attempt at development
Taiwan compatriots are right SDCC Introduction to the use of
边栏推荐
- Discussion on outsourcing safety development management and control
- MySQL-DDL
- It is the German oscilloscope software and the keysight oscilloscope upper computer software ns-scope
- Quantitative research on heterogeneous communities 4 rate of change with bands
- 旅行不能治愈心灵
- 2022年安全员-C证上岗证题目及答案
- Typescript variable declaration - type assertion
- Matrial3d parameter analysis
- MySQL 5.6.49 企业版设置密码复杂度策略
- 南京大学 静态软件分析(static program analyzes)-- Intermediate Representation 学习笔记
猜你喜欢

100w的数据表比1000w的数据表查询更快吗?

Introduction to the upper computer software ns-scope of Tektronix oscilloscope

Jenkins 通过Build periodically配置定时任务

记一次Vmware虚拟机升级GLIBC导致系统瘫痪的恢复解决方法

知识点:PCB电路板的几种特殊布线方法

Formation harmonyos I

蜜雪冰城(已黑化)

Est le logiciel d'oscilloscope allemand, le logiciel d'ordinateur hôte d'oscilloscope keysight NS scope

20N10-ASEMI中低压MOS管20N10

Jenkins configures scheduled tasks through build periodically
随机推荐
2022年138套数学分析高等代数考研真题参考解答勘误
I would like to ask you guys, the flick CDC will add a table level exclusive lock before extracting the full amount of Oracle data
One's deceased father grind politics English average cent furnace! What is your current level?
Interesting research on mouse pointer interaction
阿宽食品:“方便食品第一股”争夺战继续
XML entity injection vulnerability
Understand Flink operatorchain object reuse
Codeworks round 797 (Div. 3) F. shifting string problem solution
Use huggingface to quickly load pre training models and datasets in the moment pool cloud
华为云发布桌面IDE-CodeArts
Hands on data analysis data reconstruction
HMS core machine learning service ID card identification function to achieve efficient information entry
A Kuan food: the battle for "the first share of convenience food" continues
Illustrated with pictures and texts -- wechat applet to obtain the user's geographic location information and call Tencent map API to obtain the user's specific location
2022危险化学品经营单位安全管理人员特种作业证考试题库及在线模拟考试
记一次Vmware虚拟机升级GLIBC导致系统瘫痪的恢复解决方法
Ansible operating instructions for configuring SSH authentication free for the first time
Adapter power supply automatic test equipment | introduction to charger ATE test system nsat-8000
2-zabbix使用自动发现自动添加主机
Architect training plan - infinite thinking - variables