当前位置:网站首页>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/



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 :

 Insert picture description here

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

 Insert picture description here

2、 Storage type

 Insert picture description here

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 ):

 Insert picture description here

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

 Insert picture description here

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 .

 Insert picture description here


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 ):

 Insert picture description here

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 __SDCC macro , 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 sfrsbit 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 :

 Insert picture description here
; 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 ):

 Insert picture description here

Download it in , You can see that Hello world! In the endless printout :
 Insert picture description here

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 :

 Insert picture description here

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 :

 Insert picture description here

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

SDCC Compiler User Guide

8051 C Development Using SDCC(Small Device C Compiler)

Nuvoton N76E003 with SDCC

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

51 The development environment of single chip microcomputer is used VSCode combination SDCC replace Keil

Use Visual Studio Code + CMake + SDCC Conduct C51 An attempt at development

Taiwan compatriots are right SDCC Introduction to the use of

sdcc man Reading notes

SDCC printf Function introduction

Open source SDCC compiler ( One )-- Basic introduction

原网站

版权声明
本文为[Summer foam and light rain]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/172/202206211158514777.html

随机推荐