1.固件代码更新
2.C程序代码
#define ADR_273 0x0200
#define ADR_244 0x0400
#define LED_PORT 0x800
#define PC16550_THR 0x1f0
#define PC16550_LSR 0x1f5
/
//基本的IO操作函数
/
char str[]="Hello World! 20250531 Very Ok!!!\r\n";
char cx='A';
void outp(unsigned int addr, char data)
// 输出一字节到I/O端口
{ __asm
{ mov dx, addr
mov al, data
out dx, al
}
}
char inp(unsigned int addr)
// 从I/O端口输入一字节
{ char result;
__asm
{ mov dx, addr
in al, dx
mov result, al
}
return result;
}
//串口发送函数
void uart_send(char x)
{
int temp;
while(1)
{
temp=inp(PC16550_LSR);
if((temp&0x20)==0x20)
{
break;
}
}
outp(PC16550_THR,x);
}
void uart_str_send(char *p)
{
//int i=0;
//char str1[20]="Hello World!\r\n";
//char *p;
//p=str1;
while(*p!='\0')
{
uart_send(*p);
p++;
}
/*
for(i=0;i<14;i++)
{
uart_send(str1[i]);
}
*/
}
///
char end_flag[5]={0x55,0x55,0x55,0x55,0x55};
void main(void)
/*检测按键状态并由LED发光二极管显示,
若按键闭合对应LED发光二极管点亮,
若按键断开对应LED发光二极管灭.*/
{
int i=0;
while (1)
{
//char button_state;
//button_state=inp(ADR_244);
//int i=0;
uart_str_send(str);
uart_send(cx);
for(i=0;i<5000;i++);
for(i=0;i<5000;i++);
outp(LED_PORT, 0xff);
for(i=0;i<5000;i++);
for(i=0;i<5000;i++);
outp(LED_PORT, 0x00);
}
}
3.编译下载 测试
4.8088单板机固件代码
#make_bin#
; BIN is plain binary format similar to .com format, but not limited to 1 segment;
; All values between # are directives, these values are saved into a separate .binf file.
; Before loading .bin file emulator reads .binf file with the same file name.
; All directives are optional, if you don't need them, delete them.
; set loading address, .bin file will be loaded to this address:
#LOAD_SEGMENT=0500h#
#LOAD_OFFSET=0000h#
; set entry point:
#CS=0500h# ; same as loading segment
#IP=0000h# ; same as loading offset
; set segment registers
#DS=0500h# ; same as loading segment
#ES=0500h# ; same as loading segment
; set stack
#SS=0500h# ; same as loading segment
#SP=FFFEh# ; set to top of loading segment
; set general registers (optional)
#AX=0000h#
#BX=0000h#
#CX=0000h#
#DX=0000h#
#SI=0000h#
#DI=0000h#
#BP=0000h#
; add your code here
;---------------------------------------------------------------------------
;2017.2.2 增加字符串输出“OK...”
;2017.1.18 增加8255控制的数码管显示部分
;2017.1.17 修改led显示 加速初始化
;2016.10.9 接收到4个55H 跳转
;2016.10.7 修改程序下载后的触发方式,改成中断触发方式
;2016.10.6 增加串口接收指令集,下载到ram 0000:2000处,然后跳转到此处进行执行
;2016.10.2 将指令写到ram 0000:2000,然后串口跳转到0000:2000处进行执行
;2016.10.2 验证汇编EQU伪指令,PC16550 RECIEVE 1 BYTE
;2016.10.1 在中断中增加利用串口发送1个字节 0X99 的功能
;2016.10.1 成功对pc16550进行初始化,并且能够向PC端发送0X55 0XAA,非常高兴
;2016.9.30 增加PC16550驱动部分代码
;---------------------------------------------------------------------------
;ASM Example
;assume that the EPROM is mapped starting at FF000h
;and is 4Kbytes wide.(2732 type of device)
;
;assume that there is SRAM at 00000-OOOFFh (256 bytes)
;
;
;------------------------------------------------------*
; Packaging Program *
;This program is designed for bottle packaging in a *
;factory. The bottles pass across a sensor and for *
;each bottle the sensor sends a signal to one of the *
;input ports of the microprocessor (8Ox88). The *
;microprocessor checks to see if number of bottles has *
;reached 16. If so, the program sends another signal *
;to the packaging machine. *
;------------------------------------------------------*
;.Model small ;64K Max. size
;.Model large
;-------------------------------------------------------
;Declare some useful constants.
;inport equ 3F8h ;Input port address
;outport equ 2F8h ;Output port address
;MaxBot equ 10h ;set maximum number
;of bottles to 16
;-------------------------------------------------------
; DO NOT use a data segment. All fixed data that you
; want in ROM can be put in the code segment using the
; same compiler directives you used in the data segment
;-------------------------------------------------------
; .CODE
;ORG 0100h ;put permanent data here.
;start,of fixed data(rather arbitrary,
;only must not be at the high end of
;EPROM). The ORG statement MUST FOLLOW
;the segment declaration.
;tblstrt: db 0FFh ;Just defining some useless data.
;db 0EEh
;db 0DDh
;tblend: db 0A5h ;End of useless data
;---------------------------------------------------------
;This is where the code "really" starts!
;LCR EQU 8003H
LSR EQU 1f5H
DATA_BRDL EQU 1F0H
ORG 0000h ;keep data and code areas separate
start: nop
;-------------------------------
;init
;-------------------------------
mov ax,0
mov ds,ax
mov ss,ax
mov ax,6fffh
mov sp,ax
;-----------------------------
;init si as 2000h
;-----------------------------
mov ax,2000h
mov bx,ax
;----------------------------------------
;LIGHT LED
;---------------------------------------
;MOV AL,0FH
CALL NMI_INIT
mov al,0f0h
mov byte ptr ds:[80h],al
mov al,00h
mov byte ptr ds:[81h],al
mov al,00h
mov byte ptr ds:[1000h],al
mov byte ptr ds:[1001h],0
CALL CMD_WR
CALL COM_INIT
;-----------------------------------------------------
;main loop
;-----------------------------------------------------
mov ax,2000h
mov bx,ax
MOV DX,DATA_BRDL
;IN AL,DX
;OUT DX,AL
mov ax,bx
; out dx,ah
out dx,al
mov al,ah
out dx,al
CALL OK_STR
;-----------------------------------------------
MOV AX,0F000H
MOV ES,AX
;MOV DI,STR1
LEA DI,STR1
CALL STR_OUT
;-----------------------------------------------
; CALL OK_STR
MOV CX,200
LOOP $
;---------------------------------------------------
MOV CX,3
S100:
MOV DX,800H
MOV AL,0FFH
OUT DX,AL
CALL DELAY
CALL DELAY
MOV AL,0
OUT DX,AL
CALL DELAY
CALL DELAY
CALL OK_STR
LOOP S100
MOV DX,800H
MOV AL,0FFH
OUT DX,AL
; CALL OK_STR
call init8255
call disp_8255
; CALL OK_STR
;-----------------------------------------------
MOV AX,0F000H
MOV ES,AX
;MOV DI,STR1
;LEA DI,STR2
;CALL STR_OUT
NOP
NOP
LEA DI,STR1
CALL STR_OUT
;-----------------------------------------------
; CALL OK_STR
main:
nop
call rcv_inc
mov al,byte ptr ds:[1000h]
cmp al,55h
jnz next_p
;----------------------------------------
;初始化程序跳转前的段地址准备
;0000:2000 EQU 01f0:0100h
mov ax,01f0h
mov ds,ax
mov ss,ax
mov ax,5fffh
mov sp,ax
;-----------------------------------------
; mov byte ptr ds:[100h],00H
; mov byte ptr ds:[101h],20H
; mov byte ptr ds:[102h],00H
; mov byte ptr ds:[103h],00H
mov byte ptr ds:[3100h],00H
mov byte ptr ds:[3101h],01H ;ip=0100h
mov byte ptr ds:[3102h],0f0H
mov byte ptr ds:[3103h],01H ;cs=01f0
JMP DWORD PTR DS:[3100H]
next_p:nop
jmp main
;------------------------------------------------------
;main loop end
;------------------------------------------------------
START01:
NOP
;mov al,55h
;mov byte ptr ds:[80h],al
mov al,byte ptr ds:[80h]
;OUT 10H,AL
mov dx,0ffh
out dx,al
CALL DELAY
CALL DELAY
;CALL DELAY
;CALL DELAY
;-----------------------------------------
;OFF LED
;-----------------------------------------
;MOV AL,00H
;mov al,0aah
;mov byte ptr ds:[80h],al
mov al,byte ptr ds:[81h]
;OUT 10H,AL
mov dx,0ffh
out dx,al
CALL RCV
NOP
NOP
CALL COM_TEST
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
jmp START01 ;START again
;---------------------------------------------------
;将指令写到RAM 0000:2000处
;b0 f0 e6 10 eb fa
; loopx:mov al,0f0h
; out 10h,al
; jmp loopx
;----------------------------------------------------
CMD_WR PROC NEAR
mov byte ptr ds:[2000h],0B0H
mov byte ptr ds:[2001h],0F0H
mov byte ptr ds:[2002h],0E6H
mov byte ptr ds:[2003h],10H
mov byte ptr ds:[2004h],0EBH
mov byte ptr ds:[2005h],0FAH
RET
CMD_WR ENDP
;---------------------------------------------------
;16650 init
;---------------------------------------------------
COM_INIT PROC NEAR
;LINE
MOV AL,8AH
MOV DX,1F3H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;LSB
MOV AL,120
MOV DX,1F0H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;MSB
MOV AL,0
MOV DX,1F1H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;LINE
;MOV AL,0AH
MOV AL,03H
MOV DX,1F3H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;FIFO
MOV AL,07H
MOV DX,1F2H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
MOV DX,800H
MOV AL,0AAH
OUT DX,AL
RET
COM_INIT ENDP
;---------------------------------------------------
;16650 SEND 1 BYTE
;---------------------------------------------------
COM_TEST PROC NEAR
MOV AL,55H
MOV DX,1F0H
OUT DX,AL
CALL DELAY
MOV AL,0AAH
MOV DX,1F0H
OUT DX,AL
RET
COM_TEST ENDP
;---------------------------------------------------
;PC16550 RECIEVE 1 BYTE
;---------------------------------------------------
RCV PROC NEAR
PUSH AX
MOV DX,LSR
IN AL,DX
TEST AL,01H
JZ RCV_EXIT
MOV DX,DATA_BRDL
IN AL,DX
OUT DX,AL
;JMP WORD PTR DS:[2000H]
;MOV AX,2000H
;MOV DS:[100H],AX
;MOV WORD PTR DS:[102H],0
mov byte ptr ds:[100h],00H
mov byte ptr ds:[101h],20H
mov byte ptr ds:[102h],00H
mov byte ptr ds:[103h],00H
JMP DWORD PTR DS:[100H]
NOP
RCV_EXIT:
NOP
POP AX
RET
RCV ENDP
;--------------------------------------------------------
;pc16550 接收指令集,并写到指定的ram位置
;--------------------------------------------------------
rcv_inc proc near
PUSH AX
MOV DX,LSR
IN AL,DX
TEST AL,01H
JZ RCVinc_EXIT
MOV DX,DATA_BRDL
IN AL,DX
OUT DX,AL
;mov ax,si
;out dx,ah
;out dx,al
;mov al,ah
;out dx,al
mov byte ptr ds:[bx],al
add bx,1
;*****************************************************
;
;*****************************************************
cmp al,55h
jnz set_0
add byte ptr ds:[1001h],1
cmp byte ptr ds:[1001h],4
jnz skip
mov byte ptr ds:[1000h],55h
;mov byte ptr ds:[1001h],0
jmp skip
set_0:
mov byte ptr ds:[1001h],0
skip:
nop
;*****************************************************
cmp al,0ffh
jnz RCVinc_EXIT
jz RCVinc_EXIT
;JMP WORD PTR DS:[2000H]
;MOV AX,2000H
;MOV DS:[100H],AX
;MOV WORD PTR DS:[102H],0
mov byte ptr ds:[100h],00H
mov byte ptr ds:[101h],20H
mov byte ptr ds:[102h],00H
mov byte ptr ds:[103h],00H
;JMP DWORD PTR DS:[100H]
mov ax,5
mov cx,ax
mov ax,2000h
mov si,ax
;mov
s:
mov al,byte ptr ds:[si];
MOV DX,DATA_BRDL
OUT DX,AL
add si,1
;loop s
;cmp si,2100h
;mov cx,500
;s1: loop s1
;mov ax,1f5h
mov dx,1f5h
s2: in al,dx
test al,20h
jz s2
mov ax,si
cmp ax,2fffh
jnz s
MOV DX,DATA_BRDL
OUT DX,AL
mov al,ah
out dx,al
;JMP DWORD PTR DS:[100H]
NOP
RCVinc_EXIT:
NOP
POP AX
RET
;ret
rcv_inc endp
;---------------------------------------------------
;DELAY PROC
;---------------------------------------------------
DELAY PROC NEAR
;push
PUSH CX
PUSH BX
NOP
NOP
mov bx,10
del1:
mov cx,5882
del2:
loop del2
dec bx
jnz del1
;pop cx
;pop bx
POP BX
POP CX
RET
DELAY ENDP
;----------------------------------------------
;nop delay
;----------------------------------------------
delay_100 proc near
PUSH AX
mov al,0FFh
;INC AL
mov byte ptr ds:[80h],al
NOP
NOP
NOP
POP AX
ret
delay_100 endp
;---------------------------------------------------
;DELAY01 PROC
;---------------------------------------------------
DELAY01:
;push
NOP
NOP
mov bx,10
del10:
mov cx,5882
del20:
loop del20
dec bx
jnz del10
;pop cx
;pop bx
RET
;---------------------------------------------------------
;NMI_INIT PROC
;---------------------------------------------------------
NMI_INIT:
PUSH ES
XOR AX,AX
MOV ES,AX
MOV AL,02H
XOR AH,AH
SHL AX,1
SHL AX,1
MOV SI,AX
MOV AX,OFFSET NMI_ISR
MOV ES:[SI],AX
INC SI
INC SI
MOV BX,CS
MOV ES:[SI],BX
POP ES
RET
;--------------------------------------------------------
;NMI_ISR
;--------------------------------------------------------
NMI_ISR:
NOP
NOP
mov al,byte ptr ds:[80h]
;mov al,0FFh
INC AL
mov byte ptr ds:[80h],al
;MOV AL,0FFH
;OUT 10H,AL
;CALL DELAY01
NOP
call delay_100
;CALL DELAY
;CALL DELAY
;CALL DELAY
;-------------------------------
;DELAY
;-------------------------------
;-------------------------------
;uart send 0x99 function
;-------------------------------
mov al,55h
mov byte ptr ds:[1000h],al
MOV AL,0a5H
MOV DX,1F0H
OUT DX,AL
NOP
NOP
IRET
;-----------------------------
;8255 init
;-----------------------------
init8255 proc near
mov dx,203h
;mov al,80h
mov al,89h;port a,b as output port c as input
out dx,al
ret
init8255 endp
;------------------------------
;8255 for disp
;------------------------------
disp_8255 proc near
mov al,11000000b ;'1'
mov dx,200h
out dx,al
;8255 port b
mov al,00h
mov dx,201h
out dx,al
ret
disp_8255 endp
;---------------------------------------
;OK STR OUT
;---------------------------------------
OK_STR PROC NEAR
MOV DX,DATA_BRDL
MOV AL,'O'
OUT DX,AL
MOV AL,'K'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
RET
OK_STR ENDP
;-----------------------------------------------------------
;增加Boot启动输出“www.i8088.com”信息
;2019.11.3
;-----------------------------------------------------------
STR_OUT PROC NEAR
NOP
STR_LOOP:
MOV DX,DATA_BRDL
MOV AL,BYTE PTR ES:[DI]
CMP AL,'$'
JZ STR_EXIT
;MOV AL,'X'
OUT DX,AL
;MOV AL,'X'
;OUT DX,AL
MOV CX,200
LOOP $
INC DI
JMP STR_LOOP
STR_EXIT:
NOP
RET
STR_OUT ENDP
STR1 DB 'www.i8088.cn',13,10,'$'
STR2 DB 'just for fun!',13,10,'$'
;BLANK DB 0FFF0H-THIS
;db 3000-($-start) dup(0) ; Fill the rest of the sector with zero's
db 25520-$ dup(0) ; Fill the rest of the sector with zero's
db 45520-$ dup(0) ; Fill the rest of the sector with zero's
;db 55520-$ dup(0) ; Fill the rest of the sector with zero's
db 20000 dup(0)
; JMP far START
DB 0EAH
DB 00H
DB 00H
DB 00H
DB 0F0H
;SATRT DB 0EAH 00H 00H 00H 0F0H
;**********************************************************************
;**********************************************************************
;EPROM goes from XX000-XXFFFh. But, because of memory mapping,
;the XX is actually Ffh address. The jump must bea ;near jump (2 byte,
;relative address) so that the jump is relocatable. Otherwise
;a 4byte absolute address is put in.
;
;org 0FF0h ;restart address
; .CODE
;org 0eff0h ;27c512 64k rom,烧写时需手动移到fff0处
;jmp far ptr start;
;again: mov al,01h
;again1: out 10h,al
;jmp 0f000:0100
end
HLT ; halt!