# 注意資料要不要初始化 ## ㄏ ## ? * register, stack * CY AC N/A RS1 RS0 OV N/A P * MOV, ADD, SETB, CLR, PUSH, POP, EQU, END... :::spoiler 2ㄏ2 * ADDC, SUBB: with CY * L for bits caculation * MUL, DIV operand 只能是AB * DA A change into BDC ![image.png](https://hackmd.io/_uploads/HJV_UaJQT.png) ::: * PUSH 6 ____ ; push register6 data into stack * 可以透過更改SP地址去改變stack地點,不被限制在08~1F中 * SP 是pointer所以要用MOV SP, #xx 去改變指到的地方,#xx為地址(為immediate) * * JZ (look up A) * DJNZ, **JNZ(A)**, JNC, JNB bit offset, JBC bit offset, CPL, CJNE * JBC bit(Jump and clear),也只有SET(=1)的時候才能clear * CJNE Reg, #xx * CJNE A, data :::spoiler 2ㄏ3 ![image.png](https://hackmd.io/_uploads/rJoYwak76.png) ::: * DJNZ: 先decrease才判斷,LOOP跳回前面,所以說在判斷之前一定會先執行一次 * 這是一個do while loop 且i--擺在loop最下面,在SJMP(LCALL、ACALL)到上面(不判斷) * for, while 是用CJNE + J * 1 * 去看High, low ADD, SUB * * ## CH2 ASSEMBLY PROGRAM LANGUAGE * PUSH 6 ____ ; push register6 data into stack * 可以透過更改SP地址去改變stack地點,不被限制在08~1F中 * SP 是pointer所以要用MOV SP, #xx 去改變指到的地方,#xx為地址(為immediate) * * Mem-to-Mem never allow in 8051 assembly * Program counter (PC): * 16 bits wide * address for <font color='red'> **next** </font> instruction to be execute * as CPU fetch the OPcode PC increment to next instruciton * address <font color='red'> **0000** </font> when power up (org 0) * 所以說第一行要加org 0 * ROM is 8 bit so we need two address of ROM to construction one PC * PC = PC + <font color='red'>(instruction size)</font> * 8051 only have one data type * EQU (equal) define a constant without occupy memory(done by assembler sililer in C *#define COUNT 10, COUNT EQU 10*)<font color='red'> EQU 沒冒號 </font> * 要用immediate 去呼叫 * PSW (Program Stste Word) Register <font color='red'> **背** </font> * CY: carry out from D7 * 當兩數 * AC(auxiliary): carry out from D3 to D4 (use for BCD) * RS1: set register bank high bit * RS2: set register bank low bit * OV: overflow flag for sign calculation * P: parity flag the number in A have odd(P = 1) or even(P = 0) 1,可以理解為把A和P的1總數永遠都是偶數 :::spoiler 圖片資料 ![](https://hackmd.io/_uploads/By1CtHFzp.png) ::: * Register Bank and Stack :::spoiler 概覽 ![](https://hackmd.io/_uploads/S1PxW8tG6.png) ::: * 4 register bank contol by RS1(PS4), RS0(PS3) * <font color='red'> **Stack** </font>: * initilize be Bank 1 * PUSH: SP 先+1後才再放資料進去,所以初始化<font color='red'> **SP = 07** </font> * PSDH 4: push R4 into stack * POP: 從SP把值拿出來,之後才再把SP-1 * POP 4: pop data to R4 * 因為20~2F 為bit location,所以stack會被<font color='red'> **限制08~1F** </font>,當要用更大的stack, 就要把SP移到30~7F的位置。 * 8F以上為special function register ## CH3 JUMP, LOOP, AND CALL intstruction :::spoiler JUMP instruction CJZE: compare jump not equal ![](https://hackmd.io/_uploads/BkivtUYza.png) ::: * DJNZ<font color='red'> **先decrease才check** </font>之後才會JUMP * One DJNZ max jump 256 因為R2只有8bits * 要用Nast Loop 解決256以上的loop * JZ Jump if A = 0 * <font color='red'> Example 3.6 算PC </font> * 下一行加多少到target in 2's cmplement * 因為會先fetch 所以PC要先+,所以用下一行為標準 * 在算跳到哪都是用**下一行(當前PC指的地方)**,去用OPcode做加法(2's complement form), 把**PC = PC + OFFSET** :::spoiler CALL instruction ::: * 直接存要跳到的地址 * LCALL: * 3 byte instruction * call anywhere in 64KB address space in 8051 * 用Stack儲存要RET的地址,又因為地址是4 bytes 所以要拆成兩個Low bytes 先放進去,再放High bytes,和有被使用的register中的原始資料 * ACALL(absolute call) * 2 byte instruction * target address <font color='red'> must be in 2KB </font>, due only <font color='red'> 11 bits save offset (-512~511)</font> :::spoiler ::: * <font color='red'> Example 3.13 算Mechine cycle </font> * <font color='red'> Example 3.21 算delay time </font> * Ex: 8051: 1 mechine cycle lasts 12 oscillator, for 11.5092MHz * so a mechine take $1/f*12 = 1/11.5092M*12=1.085us$ ## CH4 I/O Port Programming * lacth: port; input pin另外一邊 * PX.X 不能直接MOV, 要透過flag 或regiter * latch: DATA 進CPU 再write back to pin 就會從latch讀資料, 會同步出現再pin上 * Pin: 只有讀data,就是看pin data, Port 的直不會改變 * <font color='red'> port 變 pin 變,pin 變 port不變</font> * 8051 有4個port 其中port 0, port 2可以傳送 * when RESET are configure as input port, 還沒輸入當然不能當輸出,也就是說REST會把全部register設成1 * 若要輸入之前要把會用到的的bit<font color='red'>先設成1,才可以作為輸入</font> * 會因為Port=0會把下拉電路MOS打開,Pin接地,就算輸入為1也會讀成0 :::spoiler 若設成0,此時輸入為1會出現錯誤,如下圖 ![](https://hackmd.io/_uploads/rJMdrEcMa.png) ::: * 也就是說若有一個0被擺進port, port就只能是輸出,直到下一個1出現去trigger port :::spoiler port 0 ::: * 需要接上拉電路,當資料要從Port出來(C = 0,Port = 1)需要上拉電路,讓pin=1 * 當control = 1 從Add/Data(memory走),Pin change latch 不會 * 當control = 0 從latch抓資料 * dual rule: allow to be used for both address and data <font color='red'>from memory</font> :::spoiler port 1 ::: * 只有GPIO的功能 * 不需要外接上拉電路(有internal) * 一樣要輸入的時候要先把port=1 :::spoiler port 2 ::: * 當control=1只會傳輸地址,不會傳輸資料(都接到的是CPU) * 不需要外接上拉電路(有internal) * 一樣要輸入的時候要先把port=1 * 一般使用到P2當地址時會搭配P0組合成16bits address :::spoiler port 3 ::: * 不需要外接上拉電路(有internal) * 有較多的功能 * 複習一下影片 * bit manipulation * SETB P1.3 * CPL P1.4 * CLR P1.2 * JB P1.2, HERE * JNB P1.2, HERE * JBC P1.2, HERE (clear P1.2) * MOV c, P2.4 (MOV to CY flag) * CJNE A. P2, HERE (compare jump not equal) :::spoiler read latch ![image.png](https://hackmd.io/_uploads/Bkgzw0yQa.png) ::: ## CH5 Addressing Mode 1. immediate (#) 2. register (R0~R7) 3. direct (address) 4. register indirect (pointer, DPTR, PC, SP, @R0, @R1) 5. index (A + Register indirect) * immediate * 凡是前面加#的都是 * MOV DPTR #1234H, 和MOV DPH #12H MOV DPL #34H 一樣 * 可以用EQU處理,因為常數是immediate * EQU沒有冒號 * Register * symbol: R0~R7 * Direct address mode * 128 byte (00h~70h) RAM * 00~1F for bank and stack * 20~2F for bit-addressable * 30~7F byte size data * <font color='red' >MOV A, 4 == MOV A, R4</font> 不是放#4到A * SFR (special function register) * 80H~FFH :::spoiler SFR structure ::: * register indirector mode * register save the target address * only R0, R1, DPTR can use for this propose * index addressing * MOVC A, @A+DPTR * DJNZ 30H, LOOP ;30H is direct, means load the number in 30H :::spoiler bit address instruction ::: * the direct means the bit in 20H~2FH * 128 bit 00H~7FH * 81H --> P0.1 ## CH6 Arithmetic, Logic Instructions, AND Programming * ADD A, source ___ ; A = A + source * destination always be A * can change all flag(CF, AF, P) * ADDC A, source ___ ; A = A + Source + CY * 做16bit 加法,High byte use ADDC * BCD(Binary coded decimal) * unpacked lower 4 bits BCD, upper are all 0s * packed: two BCD number in a byte * after adding two BCD number use <font color='red'>**DA A**</font> to correct the BCD addtion problem * <font color='red'>DA A</font>(Decimal adjust for addition) * only use A be operand * if use INC DA A will <font color='red'>not work</font> * SUBB A, source ______ A = A - source **- CY** * Use 2's complement form ADD A + source(2's) 1. change source to 2's complemet form 2. ADD A + T(source) + T(-CY) * 當再做2 byte減法,High byte就和ADDC 一樣要用SUBB把CY考慮進去 * 可以理解為向高位界一個bit * 因為當Low byte is Over 會溢位到CY * MUL AB * operand always be A and B * A = low byte, B = High byte * DIV AB A/B = A...B * IF B = 0, OV = 1 means ERROR * <font color='red'>Ex: 6.8(P21)</font> * Sign * MSB = 1 neg, MSB = 0 postive * 2's complement -128~127 * -128 = 1000,0000 * Overflow * sign number is too large for register 1. 正數+正數 MSB=1(負數), OV=1 * carry from D6 to D7 but not carry out of D7 2. 負數-負數 MSB=0(正數), OV=1 * carry out of D7 but not carry from D6 to D7 * set 1 if there is [carry from D6 to D7] XOR [D7 carry out] * Login instruction every bit(bit wise) * ANL dest, source _____ ;dest = dest AND source * ORL dest, source _____ ;dest = dest OR source * XRL dest, source _____ ;dest = dest XOR source * <font color='red'>可以抓兩個數是不是一樣 * EX6.21</font> * CPL A * compare instruction * CJNE des, source, label (compare jump not equal) <font color='red'> * destination >= source, CY = 0 * destination < source, CY = 1 </font> * Rotate (operand only be A) * RR A (ratate right) * RL A (ratate left) * RRC A (ratate right to CY) * RLC A (rotate left to CY) 1. serializing a byte of data, move a bit to CY copy CY * SWAP A * RL 4次 <font color='red'>Ex 6.34, 6.35 ASCII</font> * Checksum byte * add all data drop carry find 2's complement number * add data + checksum = 0(correct) * 若不等於0代表有ERROR