1.验证结果
2.代码片
key_code=inp(PORT_8255_C)&0x0f;
tiny_sprintf(buffer,"Key_code= 0X%x \r\n",key_code);
uart_str_send(buffer);
3.完整代码
#include "tiny_stdarg.h" // 使用自定义可变参数实现
#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 buff[60]
char cx='A';
unsigned int cs_adr=0,ds_adr=0,ss_adr=0;
/// @brief
/// @param addr
/// @param data
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 register_read(void)
{
__asm
{
mov ax,CS
mov cs_adr,ax
mov ax,DS
mov ds_adr,ax
mov ax,SS
mov ss_adr,ax
}
}
//串口发送函数
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]);
}
*/
}
///
/* sprintf()函数实现 */
/* tiny_sprintf.c */
#include "tiny_stdarg.h"
static void itoa(unsigned num, int base, char *out) {
char buf[6]; // 16位整数最大5位数字 + 结束符
char *p = buf;
int i = 0;
if (num == 0) {
*out++ = '0';
*out = '\0';
return;
}
while (num > 0) {
int r = num % base;
*p++ = (r < 10) ? (r + '0') : (r - 10 + 'a');
num /= base;
i++;
}
while (i-- > 0) {
*out++ = *--p;
}
*out = '\0';
}
int tiny_sprintf(char *buf, const char *fmt, ...) {
va_list args;
char *p = buf;
const char *s = fmt;
va_start(args, fmt);
while (*s) {
if (*s != '%') {
*p++ = *s++;
continue;
}
s++;
switch (*s) {
case 'd': {
int num = va_arg(args, int);
if (num < 0) {
*p++ = '-';
num = -num;
}
itoa(num, 10, p);
while (*p) p++;
s++;
break;
}
case 'x': {
unsigned num = va_arg(args, unsigned);
itoa(num, 16, p);
while (*p) p++;
s++;
break;
}
case 's': {
char *str = va_arg(args, char *);
while (*str) *p++ = *str++;
s++;
break;
}
case 'c': {
char c = (char)va_arg(args, int);
*p++ = c;
s++;
break;
}
case '%': {
*p++ = '%';
s++;
break;
}
default: {
*p++ = '%';
*p++ = *s++;
break;
}
}
}
*p = '\0';
va_end(args);
return p - buf;
}
///
//NMI 中断
//
/* NMI 计数器 */
volatile unsigned char nmi_count =10;
//设置中断失量表
void set_int(unsigned char int_no, void * service_proc)
{ _asm
{ push es
xor ax, ax
mov es, ax
mov al, int_no
xor ah, ah
shl ax, 1
shl ax, 1
mov si, ax
mov ax, service_proc
mov es:[si], ax
inc si
inc si
mov bx, cs
mov es:[si], bx
pop es
}
}
//中断处理函数
/*
void _interrupt near nmi_handler(void)
{
nmi_count++;
}
*/
//
//8255
//
// 定义8255端口地址 (根据原理图译码确定)
#define PORT_8255_A 0x200 // PA端口地址
#define PORT_8255_B 0x201 // PB端口地址
#define PORT_8255_C 0x202 // PC端口地址
#define PORT_8255_CTRL 0x203 // 控制寄存器地址
// 数码管段码表 (共阴极)
unsigned char seg_codes[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// 延时函数
void delay(unsigned int ms) {
for (unsigned int i = 0; i < ms; i++) {
for (unsigned int j = 0; j < 100; j++) {
// 空循环延时
}
}
}
// 初始化8255
void init_8255() {
// 控制字: 10000001 (0x81)
// A口输出, B口输出, C口输出
outp(PORT_8255_CTRL, 0x81);
}
// 显示8位数字
void display_numbers() {
unsigned char digits[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 要显示的数字
while (1) { // 按任意键退出
for (int i = 0; i < 8; i++) {
// 设置位选 (选中当前位)
outp(PORT_8255_B, ~(1 << i));
// 设置段码
outp(PORT_8255_A, ~seg_codes[digits[i]]);
// 延时保持显示
delay(1);
// 关闭当前位显示 (消除鬼影)
outp(PORT_8255_A, 0x00);
}
}
}
//
//char end_flag[5]={0x55,0x55,0x55,0x55,0x55};
extern void nmi_handler(void);
void main(void)
/*检测按键状态并由LED发光二极管显示,
若按键闭合对应LED发光二极管点亮,
若按键断开对应LED发光二极管灭.*/
{
int i=0;
char buffer[80];
unsigned char key_code=0xff; // 使用安全格式化
//tiny_sprintf(buffer, "Hex: %x\n",255);
// 使用安全格式化
tiny_sprintf(buffer,
"Decimal: %d \n"
"Hex: %x \n"
"String: %s \r\n",
-123,
0xABCD,
"Hello");
register_read();
//set_nmi_handler();
set_int(0x02, (void *)&nmi_handler);
init_8255();
while (1)
{
//char button_state;
//button_state=inp(ADR_244);
//int i=0;
//uart_str_send(str);
uart_str_send(buffer);
tiny_sprintf(buffer,"******************************************\r\n");
uart_str_send(buffer);
tiny_sprintf(buffer,"CS_ADR= 0X%x \r\n",cs_adr);
uart_str_send(buffer);
tiny_sprintf(buffer,"DS_ADR= 0X%x \r\n",ds_adr);
uart_str_send(buffer);
tiny_sprintf(buffer,"SS_ADR= 0X%x \r\n",ss_adr);
uart_str_send(buffer);
tiny_sprintf(buffer,"NMI Interrupt count=%x \r\n",nmi_count);
uart_str_send(buffer);
tiny_sprintf(buffer,"******************************************\r\n");
uart_str_send(buffer);
key_code=inp(PORT_8255_C)&0x0f;
tiny_sprintf(buffer,"Key_code= 0X%x \r\n",key_code);
uart_str_send(buffer);
//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);
//display_numbers();
}
}
char end_flag[5]={0x55,0x55,0x55,0x55,0x55};
4.项目进度