Macro definition of EMC microcontroller EM78P260

Publisher:古泉痴迷者Latest update time:2018-01-27 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

(1) The most commonly used PAGE and BANK    EMC
ICs are divided into several pages and banks. Low-end EM78P156 and others only have one bank and one page, so there is no need to switch. Newer 
ICs basically need to switch. This frequently used bank is most suitable to be made into a macro. The code is as follows: 

/*********************************************************

 






* BANK SELECTION 
*********************************************** *******/ 
BANK macro num 
if num == 0 
bc R4,6 
bc R4,7 
elseif num == 1 
bs R4,6 
bc R4,7 
elseif num == 2 
bc R4,6 
bs R4,7 
elseif num == 3 
bs R4,6 
bs R4,7 
else 
message "warring!" 
endif 
endm 

/**************************** *************************** 
* PAGE SELECTION * 
********************* **********************************/ 
PAGE macro num 
if num == 0 

bc psw,5 
bc psw,6 
elseif num == 1 
bs psw,5 
bc psw,6 
elseif num == 2 
bc psw,5 
bs psw,6 
elseif num == 3 
bs psw,5 
bs psw,6 
else 
message "warring!" 
endif 
endm 

calling format is  
BANK num (num is 0 to 3, representing 4 BANKs) 
PAGE num (num is 0 to 3, representing 4 PAGEs) 
This is much more convenient and will not go wrong. 

(2) Macros with parameters 
As an example, let’s assume that we define a macro “ FUNC ", with two parameters, the function is to simply transfer the incoming data to PORT5 and 
PORT6, to demonstrate the usage. 
First look at the definition: 

FUNC MACRO ARG1,ARG2 
MOV A,@ARG1 
MOV PORT5,A 
MOV A,ARG2 
MOV PORT6 ,A 
ENDM 

Notice why there is an @ symbol in front of ARG1? This means that the first parameter received by the macro is an immediate value, while ARG2 
does not have that symbol, which means that the second parameter received by the macro is a The address of the register. 
OK, let's see how to use it in the main program: 

FUNC 0X10, 0X20 

This is OK. When the editor compiles, it will automatically perform macro replacement, passing the immediate value 0X10 as the first parameter, and 
the content of the 0X20 register , passed as the second parameter, the result after macro replacement is equivalent to: 
MOV A,@0x10 
MOV PORT5,A 
MOV A,0x20 
MOV PORT6,A 
(3) Let’s talk about a good style of C
language There is a better programming style in the language. Let's take a C51 example:
we want to set TIMER0 in mode 1 and TIMER1 in mode 2.
The general thinking and code of the tutorial is:
look up the definition of TMOD bits in the data, and then slowly calculate , what values ​​should be given to mode 1 and mode 2, and finally write the instruction:
TMOD = 0x21;
completed...
In fact, we can also have another way, that is to write:

TMOD = CT0_MODE1 | CT1_MODE2;

some macros are used in it , the specific definition is:
#define CT0_MODE0 0x00 // Timer0/Counter0 Mode
#define CT0_MODE1 0x01
#define CT0_MODE2 0x02
#define CT0_MODE3 0x03

#define CT1_MODE0 0x00 // Timer1/Counter1 Mode
#define CT1_MODE1 0x10
#define CT1_MODE2 0x20
#define CT1_MODE3 0x30

TMOD = CT0_MODE1 | CT1_MODE2;
This should It is easy to understand, right? The "|" in the middle is the OR operation, which is the operation performed by the compiler before compiling. Specifically, CT
0_MODE1 represents 0X01 and CT1_MODE2 represents 0x20, and then the result after the "AND operation" is 0X21. Same as above. But
honestly , which method would you prefer? I would choose the second one without hesitation.

(4) Use our EMC assembly compiler to imitate this style.
Our EMC assembly compiler also supports this type of compilation operation. Let the compiler help us handle some basic operations first. Faced with the small C
compiler The functions are not surprising, but the assembly compiler can also do it, which is a little unexpected.

The function register allocation of EMC chips is really a mess. Alas, it makes me vomit blood. It's okay to use a fixed type of IC. Used a few
If it's this kind of IC, it's called depressing. An example is EM78P447 and EM78P156. The former is originally an upgraded version, but why are some controls so
different ? I have to check the DATASHEET frantically every time. In order to slow down the death of brain cells, I decided to use macros... For example: We need to turn on the TCC

A counter of EM78P260 , and we use macros with parameters to implement the initialization work. Divide into several steps 1 First define a macro, which can be used to initialize TCCA_SETUP MACRO TCCACNT clr 0x04 ; 0x04 is used as a temporary register ior 0x08 ; 0x08 is the register that controls TCCA  and a,@0xf8 ; Mask TCCA-related MOV 0x04,a  MOV a,@TCCACNT ; Read the passed parameters or a,0x04 iow 0x08 MOV a,@TCCACNT ; If TCCA is allowed, open TCCA interrupt and a,@0x04 ; Otherwise jump out directly jbc 0x03,2 jmp $+4 ior 0x0f or a,@0x08 iow 0x0f  ENDM _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ TCCA_EDGE_FALL Starting string selection */ TCCA_SETUP TCCA_DISABLE|TCCA_SRC_INT|TCCA_EDGE_RISE See it? (TCCA_DISABLE|TCCA_SRC_INT|TCCA_EDGE_RISE) A bunch of meaningful parameters, XORed and passed as a parameter to the macro TCCA_SETUP. When modifying, we can do it very easily, and we don’t even need to look up information. For example, if we want to change to external TCCA pulse counting, we only need to simply modify TCCA_SETUP TCCA_DISABLE|TCCA_SRC_EXT|TCCA_EDGE_RISE to complete. If you want to disable TCCA, change it to TCCA_DISABLE and it’s OK















































(5) Automatic register allocation
Finally, we have come to the end. We have come to the most BT part, which is also the most rewarding part. How to make registers automatically allocate space? A
big difference between assembly and C is that C variables are automatically allocated. I am jealous of it. It is such a good thing. After being abused by assembly for a long time, I
suddenly found that our EMC assembly compiler also has this function. I am so happy! Maybe some seniors have already known how to use it. So I will just
show off my skills and give you
some advice. When writing programs, we usually define a meaningful and easy-to-remember name to replace the abstract register name. For example, we define a register for temporary
variables 

TEMP EQU 0X10

. In this way, we define TEMP and use TEMP to replace the 0X10 register in the future. This is the most common way. However, the problem is that
we have to redefine TEMP EQU 0X10 every time before writing a program. Of course, it is not annoying, but we all have some
subroutines with common functions. If registers are used in the subroutines, they also need to be defined. Then when doing a project, copy a
subroutine a subroutine there. Well, there are a lot of conflicting register definitions, which must be checked carefully and slowly. If you are unlucky,
two names are defined on the same register. Well, it's terrible. A very hidden logic error comes, which is a nightmare.

However, macros can be used to automatically allocate
variables. The WICE manual also says that the usage is
TEST VAR 1
MOV A, @TEST
TEST VAR TEST+1
MOV A, @TEST.

Comparing the values ​​of A twice, we find that the first value of A is 1 and the second value of A is 2! ! This is the basic principle of variable macros. The compiler treats
it as a variable and can change it, but this change only occurs during compilation and is useless after the code is generated.
Okay, let's talk about our core and how to allocate it specifically.
First, define a macro for assigning variables. The code is as follows:

ADDR_ASSIGN MACRO REGISTER
REGISTER EQU ADDRESS 
ADDRESS VAR ADDRESS+1
ENDM 

uses a parameter, the name of the variable passed in. For example, we wrote
ADDRESS VAR 0X10 in the main program (first define the address to start assigning, we start from 0X10)
ADDR_ASSIGN Temp0
Temp0 is passed in as a parameter, which actually executes 
Temp EQU 0X10
ADDRESS = ADDRESS+1 (now ADDRESS is 0X11! Because it is a variable macro!)
Next time, if we continue to define 
ADDR_ASSIGN Temp1,
Temp1 is now automatically defined as 0X11, and then ADDRESS rolls to 0X12 for the next register definition.
This is very convenient. For example, we define a bunch of registers
ADDR_ASSIGN Temp0
ADDR_ASSIGN Temp1 
ADDR_ASSIGN Temp2
ADDR_ASSIGN Te MP3

Oh my god, this is so easy to use! ! ! We don't need to worry about which register is allocated to it. Anyway, it is allocated and
can be used. Ha~~TEST and you will know.
Involved issues 1.
Out-of-bounds problem. When it is allocated to 0X3F, a page ends, but ADDRESS continues to be added. Are you afraid? Don't worry, the compiler
has reported an error and cannot compile. In this way, there is no need to worry about out-of-bounds, and you can safely define
the involved issues 2.
How to allocate multiple banks? In fact, you can add an extra parameter when defining the macro, and then use the conditional macro to jump to the definition, but I
was afraid of trouble, so I used the following method:
/*---------------------------BANK 0 entry address-------------------------------------*/
ADDRESS VAR 0X10 ; Allocatable 0x10 ~ 0x3f
/*--------------------------- BANK 0 ----------------------------------------*/
Here are the registers we need to define./*---------------------------BANK0
debug information output----------------------------------*/
MESSAGE "Bank0 maximum allocated RAM:"
ADDR_DISP ADDRESS-1
/*-------------------------------------------------------------------------------*/

/*---------------------------BANK 1 entry address-------------------------------------*/
ADDRESS VAR 0X20 ; Allocatable 0x20 ~ 0x3f
/*--------------------------- BANK 1 ----------------------------------------*/
Here are the bank 1 we need to define
/*---------------------------BANK1 debug information output----------------------------------*/ MESSAGE
"Bank 1 maximum allocated RAM:"
ADDR_DISP ADDRESS-1
/*-------------------------------------------------------------------------------*/

How is it? Harmony, right? Strictly separate the variables. If you need to put it in bank0, fill it in the area of ​​bank0. If you need to put it in bank1,
fill it in bank1. Because at the beginning of bank1, ADDRESS is redefined as 0X20, so you can continue to
allocate . If there are multiple pages, follow the same method.
At the end of each bank, I also put two macros, they are
MESSAGE "Bank0 maximum allocated RAM:"
ADDR_DISP ADDRESS-1.
The first one simply displays text. The second one ADDR_DISP is used to show which register the maximum total allocation is.
The prototype is:
ADDR_DISP macro reg
IF reg==0x10
MESSAGE "0x10"
ELSEIF reg==0x11
MESSAGE "0x11"
ELSEIF reg==0x12
MESSAGE "0x12"
ELSEIF reg==0x13

… 
(I wrote the following myself…)
ENDM

is very simple. It just passes the last address of ADDRESS in and shows it. Because ADDRESS executes an extra self-increment instruction,
we subtract it back, and then it's OK.


Reference address:Macro definition of EMC microcontroller EM78P260

Previous article:em78p153 driver 1602 source program
Next article:Elan MCU PT2262 wireless decoding program

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号