📄 st16c554.c
字号:
/*
; File: sample.c Package:UART init
; This is a sample code to show how to initialize the UART series of chips
; from Startech Semiconductors.
; This also includes some basic external loop back thru’ two different
; ports using the FIFO capability.
; This also includes external loop back thru a different computer
*/
//#include <stdio.h>
//#include <string.h>
//#include <fcntl.h>
//#include "..\inc\st16c554.h"
#include <string.h>
#include "..\inc\option.h"
#include "..\inc\44b.h"
#include "..\inc\44blib.h"
#include "..\inc\def.h"
#include "..\inc\cache.h"
#include "..\inc\uart.h"
#include "..\inc\power.h"
#include "..\inc\dma.h"
#include "..\inc\timer.h"
#include "..\inc\rtc.h"
#include "..\inc\etc.h"
#include "..\inc\iic.h"
#include "..\inc\stop.h"
#include "..\inc\extdma.h"
#include "..\inc\tp.h"
#include "..\inc\usb.h"
#include "..\inc\kb.h"
#include "..\inc\Pwm.h"
#include "..\inc\led.h"
#include "..\inc\lcd.h"
#include "..\inc\lcdlib.h"
#include "..\inc\44blcd.h"
#include "..\inc\slib.h"
#define UART_CLK 1843200.0
#define TRUE 1
#define FALSE 0
/* These are the various offsets for the registers inside the chip */
#define RHR 0x00 /* Receive Holding Register */
#define THR 0x00 /* Receive Holding Register */
#define IER 0x01 /* Interrupt Enable Register */
#define FCR 0x02 /* FIFO control Register */
#define ISR 0x02 /* Interrupt Status Register */
#define LCR 0x03 /* Line control register */
#define MCR 0x04 /* Modem Control Register */
#define LSR 0x05 /* Line Status Register */
#define MSR 0x06 /* Modem Status Register */
#define SCR 0x07 /* Scratch pad Register */
/* This two offsets are used for defining the baud rate */
#define DIVLSB 0x00 /* Divisor LSB latch address */
#define DIVMSB 0x01 /* Divisor MSB Latch address */
/*\
* Program table for baud rate
* This represents the LSB and MSB divisor latch data
\*/
char baud_table[8][2] = {
{ 0x80, 0x01 }, /* 300 */
{ 0x60, 0x00 }, /* 1200 */
{ 0x30, 0x00 }, /* 2400 */
{ 0x0c, 0x00 }, /* 9600 */
{ 0x06, 0x00 }, /* 19K */
{ 0x03, 0x00 }, /* 38k */
{ 0x02, 0x00 }, /* 56k */
{ 0x01, 0x00 } /* 115k */
};
/* Baud Rates */
#define _COM_300_ 0
#define _COM_1200_ 1
#define _COM_2400_ 2
#define _COM_9600_ 3
#define _COM_19K_ 4
#define _COM_38K_ 5
#define _COM_56K_ 6
#define _COM_115K_ 7
/* Parity */
#define _COM_NOPARITY_ 0
#define _COM_ODDPARITY_ 1
#define _COM_EVENPARITY_ 2
/* Stopbits */
#define _COM_STOP1_ 0
#define _COM_STOP2_ 1
#define _COM_STOP1_5_ 1
/* word length */
#define _COM_CHR5_ 0
#define _COM_CHR6_ 1
#define _COM_CHR7_ 2
#define _COM_CHR8_ 3
/* word length */
#define _COM_FIFO1_ 0
#define _COM_FIFO4_ 1
#define _COM_FIFO8_ 2
#define _COM_FIFO14_ 3
// 引入 inportb和outportb汇编语言子程序声明
// 注意颠倒参数的前后顺序
void outportb(U32, U8);
void outportw(U32, U16);
void outportl(U32, U32);
U8 inportb(U32);
U16 inportw(U32);
U32 inportl(U32);
#define printf Uart_Printf
void Delay(int);
void Init_16c554(void)
{
// 中断 INTA
rPCONG &= ~ 0xc000; // GPG7(INTA) input
rPUPG |= 0x80; // GPG7 pullup disable
// 数据 D0-7
rPCOND &= ~ 0xffff; // GPD7-0(D7-0) input
rPUPD |= 0xff; // GPD7-0 pullup disable
// 中断选择 INTSEL
rPDATF |= 0x80; // GPF7(INTSEL) = 1
rPCONF &= ~ 0xc000; // GPF7 output
rPCONF |= 0x4000;
rPUPF |= 0x80; // GPF7 pullup disable
// 复位 RESET 地址 A0-3
rPDATE |= 0x8; // GPE3(RESET) = 1
rPCONE &= ~ 0xf3c0; // GPE3 4 6 7 (RESET A0 A1 A2)output
rPCONE |= 0x5140;
rPUPE |= 0xd8; // GPE3 4 6 7 pullup disable
// 片选 -CSA -CSB -CSC -CSD 写选通 -IOW 读选通 -IOW
rPDATC |= 0x3f0; // GPC4-9(-CSA -CSB -CSC -CSD -IOW -IOR) = 1
rPCONC &= ~ 0xfff00; // GPC4-9 output
rPCONC |= 0x55500;
rPUPC |= 0x3f0; // GPC4-9 pullup disable
// 中断信号INTA INTB INTC INTD
rPCONG &= ~0xff00; // GPG4-7(INTA-D) input
rPUPG |= 0xf0; // GPG4-7 pullup disable
// 复位延时100ms
Delay(1000);
// RESET = 0
rPDATE &= ~ 0x8;
Delay(1000);
/*
rPCONB |= 0x200; // 选择nGCS4
rBANKCON4 = 0x3f00; // 0x2ff0; // 0x2b40;
rBWSCON &= ~ 0x0f0000;
rPDATG = 0x0c; // GPG2(INTSEL)=1,GPG3(RESET)=1
rPCONG = 0x50; // GPG2 GPG3输出
rPUPG &= ~0x0c; // GPG2 GPG3上拉使能
rPDATF = 0x08; // GPF3(电源使能)=1
rPCONF = 0x40; // GPG3输出
// rPUPF = 0xf7; // GPG3上拉使能
Delay(100); // 延时10ms
rPDATG &= ~0x08;// GPG3(RESET)=0
*/
/*
rPDATG = 0x0c; // GPG2(INTSEL)=1,GPG3(RESET)=1
rPCONG = 0x50; // GPG2 GPG3输出
rPUPG &= ~0x0c; // GPG2 GPG3上拉使能
rPDATF = 0x08; // GPF3(电源使能)=1
rPCONF = 0x40; // GPG3输出
// rPUPF = 0xf7; // GPG3上拉使能
Delay(100); // 延时10ms
rPDATG &= ~0x08;// GPG3(RESET)=0
rPDATC |= 0x30;
rPDATC &= ~ 0xe0;
rPCONC &= ~ 0x0ffc;
rPCONC |= 0x554;
rPUPC |= 0x3e;
rPCOND &= ~ 0xffff; // PGD0-7 Input
rPUPD &= ~ 0xff; // PGD0-7 Pullup
*/
}
// 向16C554 addr 寄存器写一个字节
uart_write(U8 port,U8 addr,U8 dat)
{
U32 temp;
// 地址换算到 GPE7 6 4
temp = (addr & 0x6) << 5;
temp |= (addr & 0x1) << 4;
// 地址输出
rPDATE &= ~ 0xd0; // A2-0 = 0
rPDATE |= temp;
// 片选换算到 GPC4-7 (port 0-3)
temp = ( 1 << ( 4 + port % 4));
// 片选输出
rPDATC &= ~ temp;
// 数据输出
rPDATD = dat;
// 数据线方向改为输出
rPCOND |= 0x5555;
// nWE 输出低
rPDATC &= ~ 0x100;
// 延时
Delay(1);
// nWE nOE 输出高
rPDATC |= 0x300;
// 数据线方向改为输入
rPCOND &= ~ 0xffff;
// 片选失效
rPDATC |= 0xf0;
}
// 从C554 addr 寄存器读一个字节
U8 uart_read(U8 port,U8 addr)
{
U32 temp;
// 地址换算到 GPE7 6 4
temp = (addr & 0x6) << 5;
temp |= (addr & 0x1) << 4;
// 地址输出
rPDATE &= ~ 0xd0; // A2-0 = 0
rPDATE |= temp;
// 片选换算到 GPC4-7 (port 0-3)
temp = ( 1 << ( 4 + port % 4));
// 片选输出
rPDATC &= ~ temp;
// nOE 输出低
rPDATC &= ~ 0x200;
// 延时
Delay(1);
// 得到数据
temp = rPDATD;
// nWE nOE 输出高
rPDATC |= 0x300;
// 片选失效
rPDATC |= 0xf0;
return temp;
}
// 串口设置
// port 0-4 对应 A-D 4个串口
void uart_init(U8 port,U32 baud)
{
// LCR7 = 1
uart_write(port,LCR,0x80);
// 波特率换算设置
baud = UART_CLK / 16 / baud;
uart_write(port,DIVLSB,baud);
uart_write(port,DIVMSB,baud >> 8);
// 8个数据位 1个停止位 无校验位
uart_write(port,LCR,0x03);
// 使能FIFO 和 中断
uart_write(port,FCR,0x07);
// 使能发送和接受中断
uart_write(port,IER,0x01);
// 使能串口中断
// uart_write(port,MCR,0x08);
}
int uart_check(void)
{
U8 i;
Uart_Printf("Writing aah to scr(0x07)\n");
uart_write(0,SCR,0xaa);
i = uart_read(0,SCR);
Uart_Printf("Reading back %2xh from scr(0x07)\n\n",i);
if(i == 0xaa)
return TRUE;
else
return FALSE;
}
void uart_loop(void)
{
U8 tmp;
while(1)
{
if(uart_read(0,LSR) & 0x01)
{
tmp = uart_read(0,RHR);
Delay(1);
uart_write(0,THR,tmp);
}
}
}
void uart_putch(U8 port,U8 ch)
{
uart_write(port,THR , ch);
}
/*\
* This function checks the existence of a port.
* It is very simple. Take the port address then write to the scratch pad
* an the read it back. If the data read back the same as one that was
* written then return TRUE else return FALSE.
\*/
int
check_port(com_port)
int com_port;
{
int i;
U32 k = 0x8000000 + 0x10000 * com_port + SCR;
printf("Checking for port %4xH\n",com_port);
/* Write 1010 1010 (0xaa) to scratch pad*/
printf("Writing AAH in %4xH\n",com_port);
outportb(/*0x8000000 + 0x10000 * com_port + SCR*/ k , 0xaa);
/* read it back. If it the same then return TRUE */
outportb(0,0);
i = inportb(/*com_port + SCR*/ k);
printf("Read back %2xH from %4xH\n",i,com_port);
if( i == 0xaa)
return TRUE;
else
return FALSE;
}
/*\
* This is the work horse function which actually setups the UART.
* It needs to know every thing.
\*/
int
init_uart(port,baud,parity,data,stop,fifo,trigger)
int port,baud,parity,data,stop,fifo,trigger;
{
char lcr_byte;
/* Set divisor latch */
outportb(0x8000000 + 0x10000 * port+LCR, 0x80) ;
printf("Divisor Latch is %2xH %2xH (High Low)\n",
baud_table[baud][1],baud_table[baud][0]);
outportb(0x8000000 + 0x10000 * port+DIVLSB, baud_table[baud][0]) ;
outportb(0x8000000 + 0x10000 * port+DIVMSB, baud_table[baud][1]) ;
/* Reset to normal Programming */
/* Program the lcr_byte for the above parameters */
lcr_byte = 0x00;
lcr_byte = data; /* Set the bit0 & bit1 for word length */
lcr_byte |= stop << 3; /* Set the bit2 for stop bit */
if(parity != _COM_NOPARITY_) {
lcr_byte |= 1 << 4; /* Set the bit3 for parity */
if(parity == _COM_EVENPARITY_)
lcr_byte |= 1 << 5; /* Set the bit4 for EVEN parity */
}
printf("LCR byte is %2xH\n",lcr_byte);
/* Program LCR */
outportb(0x8000000 + 0x10000 * port+LCR, lcr_byte) ;
if(fifo) {
char fifo_byte;
printf("Programming FIFOs without DMA mode\n");
/* Have to first set the fifo enable */
fifo_byte = 0x01;
outportb(0x8000000 + 0x10000 * port+FCR,fifo_byte);
/* Now program the FIFO */
fifo_byte = 0x07; /* set bit0 - FIFO enable, Reset RCVR and XMIT FIFO */
fifo_byte |= trigger << 7; /* set bit6 and bit7 with the trigger level */
/* Program FCR */
outportb(0x8000000 + 0x10000 * port+FCR,fifo_byte);
if(~(inportb(0x8000000 + 0x10000 * port + ISR) & 0xc0)) {
printf("This port %4xH does not have FIFOs\n");
printf("Hence did not program Enable FIFOs\n");
}
}
/* Program IER */
printf("Programming IER for interrupt on bit0 RCV holding Register\n");
outportb(0x8000000 + 0x10000 * port+IER, 0x01);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -