⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 DOS 下的串口编程
💻 C
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mem.h>
#include <ctype.h>
#include <dos.h>
#include <conio.h>

typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
typedef          char int8;

#define VENDOR_ID 0x1409
#define DEVICE_ID 0x7168

#define OSC_FREQ 14745600

#define SUCCESS 0
#define SET 0

#define PCI_OFFSET_BASE_ADDRESS 0x10

#define COM_OFFSET_LCR 0x3
#define COM_OFFSET_FCR 0x2
#define COM_OFFSET_MCR 0x4
#define COM_OFFSET_IER 0x1
#define COM_OFFSET_IIR 0x2
#define COM_OFFSET_LSR 0x5
#define COM_OFFSET_MSR 0x6
#define COM_OFFSET_RBR 0x0
#define COM_OFFSET_THR 0x0
#define COM_OFFSET_DIVISOR_LSB 0x0
#define COM_OFFSET_DIVISOR_MSB 0x1

#define REG_WR(address, data) outportb(address, data)
#define REG_RD(address) inportb(address)

#define GET_BUAD_DIVISOR(rate) (OSC_FREQ/(rate*16))
#define COM_CHK_DSR(base_address)  (((REG_RD(base_address+COM_OFFSET_MSR))&0x20)==0)
#define COM_CHK_DR(base_address)	 (((REG_RD(base_address+COM_OFFSET_LSR))&0x01)==0)
#define COM_CHK_THRE(base_address) (((REG_RD(base_address+COM_OFFSET_LSR))&0x20)==0)
#define COM_CHK_CTS(base_address)	 (((REG_RD(base_address+COM_OFFSET_MSR))&0x10)==0)

#define COM_OP_ARG_FIFO 1
#define COM_OP_ARG_INTR 1
#define COM_OP_ARG_AUTOFLOW 1

typedef struct {
	uint8	fifo;
	uint8	intr;
	uint8	autoflow;
	uint8	trigger;
	uint32  baudrate;
	}tCOM_OP_ARG;

typedef struct {
	uint8	*pdata;
	uint8	offset;
	uint8	num_data;
	uint8   num_tx_1cycle;
	}tDATA_TX_CTRL;

typedef struct {
	uint8	*pdata;
	uint8	offset;
	uint8	num_data;
	}tDATA_RX_CTRL;

uint8 find_pci_device(uint16 venid, uint16 devid, uint16 index, uint16 *businfo)
{
	uint8 	rc;
	uint16  temp;

	asm{
		mov ax, 0xb102;
		mov cx, devid;
		mov dx, venid;
		mov si, index;
		int 0x1a;
		mov temp, bx;
		mov rc, ah;
	}
	*businfo = temp;
	return rc;
}

uint8 read_configuration_word(uint16 businfo, uint16 ofset, uint16 *data)
{
	uint8 rc;
	uint16 temp;

	asm{
		mov ax, 0xb109;
		mov bx, businfo;
		mov di, ofset;
		int 0x1a;
		mov temp, cx;
		mov rc, ah;
	}
	*data = temp;
	return rc;
}

uint8 write_configuration_word(uint16 businfo, uint16 ofset, uint16 data)
{
	uint8 rc;
	uint16 temp = data;

	asm{
		mov ax, 0xb10c;
		mov bx, businfo;
		mov di, ofset;
		mov cx, temp;
		int 0x1a;
		mov rc, ah;
	}
	return rc;
}

void delay(uint16 delay_time)
{
	uint16	i;
	uint16	j;

	for (i=delay_time;i--;i>0)
	{
		for (j=0xffff;j--;j>0)
		{
			;
		}
	}
}

void com_buad_set(uint16 base_address, uint32 rate)
{
	uint16 divisor;
	uint8 temp;

	divisor = GET_BUAD_DIVISOR(rate);
	temp = REG_RD(base_address+COM_OFFSET_LCR);
	temp = temp|0x80;
	REG_WR(base_address+COM_OFFSET_LCR, temp);
	REG_WR(base_address+COM_OFFSET_DIVISOR_LSB, divisor&0x00FF);
	REG_WR(base_address+COM_OFFSET_DIVISOR_MSB, ((divisor>>8)*0x00FF));
	temp = temp&(~(0x80));
	REG_WR(base_address+COM_OFFSET_LCR, temp);
}

void com_init(uint16 base_address, tCOM_OP_ARG *com_op_arg_list)
{
	uint8 temp;

	com_buad_set(base_address, com_op_arg_list->baudrate);
	REG_WR(base_address+COM_OFFSET_LCR, 0x03); // 8bits 1stop no parity
	if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
		REG_WR(base_address+COM_OFFSET_FCR, 0x07|((com_op_arg_list->trigger-1)<<6));
	else
		REG_WR(base_address+COM_OFFSET_FCR, 0);
	if (com_op_arg_list->autoflow == COM_OP_ARG_AUTOFLOW)
		REG_WR(base_address+COM_OFFSET_MCR, 0x23);
	else
		REG_WR(base_address+COM_OFFSET_MCR, 0x03);
	if (com_op_arg_list->intr == COM_OP_ARG_INTR)
		REG_WR(base_address+COM_OFFSET_IER, 0x0f);
	else
		REG_WR(base_address+COM_OFFSET_IER, 0);
	temp = REG_RD(base_address+COM_OFFSET_IIR);
	temp = REG_RD(base_address+COM_OFFSET_LSR);
	temp = REG_RD(base_address+COM_OFFSET_MSR);
	temp++;
}

void com_poll_rx_auto(uint16 base_address, uint8 *data)
{
	uint8 i = 0;

//	printf("com_poll_rx_auto LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));

	while (COM_CHK_DR(base_address) == SET)
	{
		// check errors
		if ((((REG_RD(base_address+COM_OFFSET_LSR))>>1)&0x07)==0)
		{
			*(data+i) = REG_RD(base_address+COM_OFFSET_RBR);
			i++;
		}
	}
	if (i != 0)
	{
		*(data+i+1) = '\0';
	}
}

void com_poll_rx_manu(uint16 base_address, uint8 *data)
{
	uint8 i = 0;
	uint8 temp = 0;

//	printf("com_poll_rx_manu LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));

	temp = REG_RD(base_address+COM_OFFSET_MCR);
	temp = temp&(~(0x02));
	REG_WR(base_address+COM_OFFSET_MCR, temp);

	while (COM_CHK_DR(base_address) == SET)
	{
		// check errors
		if ((((REG_RD(base_address+COM_OFFSET_LSR))>>1)&0x07)==0)
		{
			*(data+i) = REG_RD(base_address+COM_OFFSET_RBR);
			i++;
		}
	}

	temp = temp|0x02;
	REG_WR(base_address+COM_OFFSET_MCR, temp);

	if (i != 0)
	{
		*(data+i+1) = '\0';
	}
}

void com_poll_tx_manu(uint16 base_address, tDATA_TX_CTRL	*data_tx_ctrlbox)
{
	uint8	i = 0;

//	printf("com_poll_tx_manu LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
	if (COM_CHK_THRE(base_address) == SET)
	{
		i = data_tx_ctrlbox->offset;
		while(((i-data_tx_ctrlbox->offset) <= (data_tx_ctrlbox->num_tx_1cycle-1))&&(i <= (data_tx_ctrlbox->num_data-1)))
		{
			if (COM_CHK_CTS(base_address) != SET)
				break;
			REG_WR(base_address+COM_OFFSET_THR, *(data_tx_ctrlbox->pdata+i));
			i++;
		}
		data_tx_ctrlbox->offset = i;
	}
}

void com_poll_tx_auto(uint16 base_address, tDATA_TX_CTRL	*data_tx_ctrlbox)
{
	uint8	i = 0;

//	printf("com_poll_tx_auto LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
	if (COM_CHK_THRE(base_address) == SET)
	{
		i = data_tx_ctrlbox->offset;
		while(((i-data_tx_ctrlbox->offset) <= (data_tx_ctrlbox->num_tx_1cycle-1))&&(i <= (data_tx_ctrlbox->num_data-1)))
		{
			REG_WR(base_address+COM_OFFSET_THR, *(data_tx_ctrlbox->pdata+i));
			i++;
		}
		data_tx_ctrlbox->offset = i;
	}
}

void print_pci_config_space(uint16 businfo)
{
	uint16 temp, i, pciconfig[32];

	for (i=0;i<0x40;i+=2)
	{
		if (read_configuration_word(businfo, i, &temp) == SUCCESS)
		{
			pciconfig[i/2] = temp;
		}
	}
	printf("\n\\**********************************\\");
	printf("\n\\**** PCI CONFIGURATION SPACE *****\\");
	printf("\n\\**********************************\\\n");
	printf("Device ID = %x	Vendor ID = %x\n", pciconfig[1], pciconfig[0]);
	printf("Status = %x  Command = %x\n", pciconfig[3], pciconfig[2]);
	printf("Class Code = %x  Revision ID = %x\n", (pciconfig[5]<<8)|(pciconfig[4]>>8), pciconfig[4]&0x00ff);
	printf("BIST = %x  Header Type = %x  Latency Timer = %x  Cache Line = %x\n", pciconfig[7]>>8, pciconfig[7]&0x00ff, pciconfig[6]>>8, pciconfig[6]&0x00ff);
	printf("Base Address 0 = %x\n", (pciconfig[9]<<16)|pciconfig[8]);
	printf("Base Address 1 = %x\n", (pciconfig[11]<<16)|pciconfig[10]);
	printf("Base Address 2 = %x\n", (pciconfig[13]<<16)|pciconfig[12]);
	printf("Base Address 3 = %x\n", (pciconfig[15]<<16)|pciconfig[14]);
	printf("Base Address 4 = %x\n", (pciconfig[17]<<16)|pciconfig[16]);
	printf("Base Address 5 = %x\n", (pciconfig[19]<<16)|pciconfig[18]);
	printf("CardBus CIS pointer = %x\n", (pciconfig[21]<<16)|pciconfig[20]);
	printf("Subsystem Device ID = %x  Subsystem Vendor ID = %x\n", pciconfig[23], pciconfig[22]);
	printf("Expansion ROM Base Address = %x\n", (pciconfig[25]<<16)|pciconfig[24]);
	printf("Reserved = %x\n", (pciconfig[27]<<16)|pciconfig[26]);
	printf("Reserved = %x\n", (pciconfig[29]<<16)|pciconfig[28]);
	printf("Max_Lat = %x  Min_Gnt = %x IRQ Pin = %x IRQ Line = %x\n", pciconfig[31]>>8, pciconfig[31]&0x00ff, pciconfig[30]>>8, pciconfig[30]&0x00ff);
}

void get_user_arg(tCOM_OP_ARG *com_op_arg_list)
{
	uint32 temp = 0;
	uint8  tstr[10];

	printf("\n\\**********************************\\");
	printf("\n\\*** COM Operation Mode Setting ***\\");
	printf("\n\\**********************************\\");

	while (1)
	{
		printf("\nNeed FIFO or not? (y or n)\n");
		scanf("%s", &tstr);
		if (strcmp(tstr, "y") == SUCCESS)
		{
			com_op_arg_list->fifo = COM_OP_ARG_FIFO;
			break;
		}
		else if (strcmp(tstr, "n") == SUCCESS)
		{
			com_op_arg_list->fifo = !COM_OP_ARG_FIFO;
			com_op_arg_list->trigger = 0;
			break;
		}
		else
			printf("Arg is illegal!\n");
	}

	if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
	{
		while (1)
		{
			printf("\nSet FIFO trigger level. (1:1Byte; 2:4Bytes; 3:8Bytes; 4:14Bytes)\n");
			scanf("%s", &tstr);
			temp = atoi(tstr);
			if (temp>=1 && temp<=4)
			{
				com_op_arg_list->trigger = temp;
				break;
			}
			else
				printf("Arg is illegal!\n");
		}
	}

	while (1)
	{
		printf("\nintr mod or polled mod? (intr or polled)\n");
		scanf("%s", &tstr);
		if (strcmp(tstr, "intr") == SUCCESS)
		{
			com_op_arg_list->intr = COM_OP_ARG_INTR;
			break;
		}
		else if (strcmp(tstr, "polled") == SUCCESS)
		{
			com_op_arg_list->intr = !COM_OP_ARG_INTR;
			break;
		}
		else
			printf("Arg is illegal!\n");
	}

	while (1)
	{
		printf("\nEnable autoflow control or not? (y or n)\n");
		scanf("%s", &tstr);
		if (strcmp(tstr, "y") == SUCCESS)
		{
			com_op_arg_list->autoflow = COM_OP_ARG_AUTOFLOW;
			break;
		}
		else if (strcmp(tstr, "n") == SUCCESS)
		{
			com_op_arg_list->autoflow = !COM_OP_ARG_AUTOFLOW;
			break;
		}
		else
			printf("Arg is illegal!\n");
	}

	while (1)
	{
		printf("Set com baud rate.\n");
		scanf("%s", &tstr);
		temp = atol(tstr);
		if (temp <= 921600)
		{
			com_op_arg_list->baudrate = temp;
			break;
		}
		else
			printf("Arg is illegal!\n");
	}
}

void com_poll_run(uint16 base_address, tCOM_OP_ARG *com_op_arg_list, uint8 *data_tx, uint8 *data_rx)
{
	uint8 temp;
	tDATA_TX_CTRL	data_tx_ctrlbox;

	void (*pcom_poll_tx)(uint16 base_address, tDATA_TX_CTRL	*data_tx_ctrlbox);
	void (*pcom_poll_rx)(uint16 base_address, uint8 *data);

	data_tx_ctrlbox.pdata = data_tx;
	data_tx_ctrlbox.num_data = strlen(data_tx);
	data_tx_ctrlbox.offset = 0;

	if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
		data_tx_ctrlbox.num_tx_1cycle = 16;
	else
		data_tx_ctrlbox.num_tx_1cycle = 1;

	if (com_op_arg_list->autoflow == COM_OP_ARG_AUTOFLOW)
	{
		pcom_poll_tx = com_poll_tx_auto;
		pcom_poll_rx = com_poll_rx_auto;
	}
	else
	{
		pcom_poll_tx = com_poll_tx_manu;
		pcom_poll_rx = com_poll_rx_manu;
	}

	printf("data_rx=");

	while (1)
	{
		if (data_tx_ctrlbox.offset <= (data_tx_ctrlbox.num_data-1))
			(*pcom_poll_tx)(base_address, &data_tx_ctrlbox);

		(*pcom_poll_rx)(base_address, data_rx);
		if (*data_rx != '\0')
		{
			printf("%s", data_rx);
			memset(data_rx, 0, 31*sizeof(uint8));
		}

		if (kbhit())
		{
			temp = getch();
			if (temp == 27) // Press Esc
				return;
		}
	}
}

void com_intr_run(uint16 base_address, tCOM_OP_ARG *com_op_arg_list, uint8 *data_tx, uint8 *data_rx)
{

}

void main(void)
{
	uint16 		temp, businfo, base_address;
	uint8 		data_tx[31], data_rx[31], tstr[10];
	tCOM_OP_ARG	com0_op_arg_list;

	// find pci device
	if(find_pci_device(VENDOR_ID, DEVICE_ID, 0, &temp) == SUCCESS)
		businfo = temp;
	else
	{
		printf("Device NOT Found!!!");
		return;
	}

	print_pci_config_space(businfo);

//       	write_configuration_word(businfo, PCI_OFFSET_BASE_ADDRESS, 0x4001);

	if (read_configuration_word(businfo, PCI_OFFSET_BASE_ADDRESS, &temp) == SUCCESS)
	{
		base_address = temp&(~(0x01));
		printf("base_address1=%x\n", base_address);
	}

	get_user_arg(&com0_op_arg_list);

	com_init(base_address, &com0_op_arg_list);


	while(1)
	{
		if (COM_CHK_DSR(base_address) != SET)
		{
			printf("\nDST is not ready. Wait for a while to check again.");
			delay(0xffff);
			continue;
		}

		printf("\n\\**********************************\\");
		printf("\n\\*** COM Operation   **************\\");
		printf("\n\\**********************************\\");

		while(1)
		{
			printf("\nWhat do you want do?");
			printf("\n1 Tx a data.");
			printf("\n2 Re-set COM operation arguments.");
			printf("\n3 Print COM Setting.");
			printf("\n4 Exit.");
			printf("\nYour choice:");
			scanf("%s", &tstr);
			temp = atoi(tstr);
			if (temp>=1 && temp<=4)
				break;
		}

		switch (temp)
		{
			case 1:
			{
				printf("\nPlease enter words you want to tx. (less than 30 words)\n");
				scanf("%s", &data_tx);

				memset(data_rx, 0, 31*sizeof(uint8));

				if (com0_op_arg_list.intr == COM_OP_ARG_INTR)
					com_intr_run(base_address, &com0_op_arg_list, data_tx, data_rx);
				else
					com_poll_run(base_address, &com0_op_arg_list, data_tx, data_rx);
				break;
			}
			case 2:
			{
				get_user_arg(&com0_op_arg_list);
				com_init(base_address, &com0_op_arg_list);
				break;
			}
			case 3:
			{
				print_pci_config_space(businfo);
				break;
			}
			case 4:
				exit(0);
			default:;
		}
/*
		if (com0_op_arg_list.intr == COM_OP_ARG_INTR)
			com_intr_run_1cycle(base_address, data_tx, data_rx);
		else
			com_poll_run_1cycle(base_address, data_tx, data_rx);
*/
	}

/*
	while(1)
	{
		if (COM_CHK_DSR(base_address) == SET)
		{
			com_poll_rx(base_address, data_rx);
			com_poll_tx(base_address, data_tx);
			if (data_rx != 0)
			{
				printf("data_tx=%s\n", data_tx);
				printf("data_rx=%s\n", data_rx);
			}
		}
	}
*/
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -