这两天对S3C44B0的串口进行了调试,了解了一些配置尝试,记录下来,作为总结。
串口调试的过程:
第一步:系统初始化
1.由 AREA reset, CODE, READONLY 进入 ResetEntry
2.由 b SYS_RST_HANDLER 跳转到系统复位代码起始处。禁止IRQ,FIQ中断,进入超级用户模式
3.由 bl InitSystem 进入系统初始化代码。该步骤包括禁止看门狗,禁止中断,设置时钟控制寄存器,为BDMA改变BDMACON寄存器的复位值,设定存储器控制寄存器。
4.初始化用户模式。如果未初始化,则进入超级用户模式。
5.初始化ram的值。
6.设定IRQ处理程序入口,并进入C环境。
第二步:端口初始化及主函数调试
1.系统时钟初始化。计算MDIV,PDIV,SDIV及Fpllo的置,配置锁相环配置寄存器。
2.定时器初始化。使用定时器5 ,设定rTCNTB5值。(如果不使用定时器延时,可以不用设置)
3.串口0的线控制寄存器ULCON0设置,UART控制寄存器UCON0设置,波特率除数寄存器UBRDIV0设置,其他的可以采用默认设置。要注意的就是波特率除数寄存器的设置:
rUBRDIV0 = ((int)(mclk/16./baud + 0.5) -1);
其中mclk的值等于第一步中计算出的Fpllo。
4.编写自己的字符串发送程序,该字符串发送程序由单个字符发送程序循环执行,判断肌肤结束组成。单个字符发送程序主要利用了UART的发送接受状态寄存器UTRSTAT0来判断发送移位寄存器,发送缓冲是否为空,接收缓冲寄存器是否准备好,这样就能进行单个字符的发送与接受。
5.main函数的编写。由于超级终端反映速度较慢,通常采用发送后延时几个ms的方式保证正确接收和显示。另外,又是也需要延时一定时间后显示或执行某个功能。Delay( )函数就是专用延时程序,利用了定时器5来实现。
#include "../inc/def.h"
#include "../inc/board.h"
#include "../inc/config.h"
/****************************************************************************
【功能说明】系统主函数
****************************************************************************/
void Main(void)
{
SystemClockInit();
TimerInit(TIMER_FREQ);
myuart_init();
myuart_send("this is a test!\n");
myuart_send("this is a uart test!\n");
myuart_send("2006.3.15\n");
myuart_send("蔡超!\n");
myuart_send("继续下一个测试\n");
while(1)
{
myuart_send("press the stop button and try later\n");
Delay(1000);
}
}
//***************************************************************************
***************************************************************************
***************************************************************************
#include "../inc/def.h"
#include "../inc/44B.h"
#include "../inc/config.h"
#include "../inc/board.h"
static U16 SerialPortSel;
static struct{
U32 mclk;
U32 pclk;
U32 sclk;
U32 freq;
} ClkPara;
void myuart_init()
{
SerialChgBaud(DEFAULT_SERIAL_BAUD);
}
void SerialChgBaud(U32 baud)
{
U32 mclk = GetCpuClock();
rUFCON0 = 0x0; //FIFO disable
rUFCON1 = 0x0;
rUMCON0 = 0x0;
rUMCON1 = 0x0;
rPCONE =(rPCONE&0xfc3)|0xeb;
rPUPE =0x6;
//UART0
// rULCON0 = 0x7; //Normal,No parity,2 stop,8 bit
rULCON0 = 0x3; //Normal,No parity,1 stop,8 bit
rUCON0 = 0x245; //rx=edge,tx=level,disable timeout int.,enable rx error int.,normal,interrupt or polling
rUBRDIV0 = ((int)(mclk/16./baud + 0.5) -1);
//UART1
// rULCON1 = 0x7; //Normal,No parity,2 stop,8 bit
rULCON1 = 0x3;
rUCON1 = 0x245;
rUBRDIV1 = ((int)(mclk/16./baud + 0.5) -1);
}
void myuart_send_byte(char ch)
{
SerialPortSel=0;
if(SerialPortSel==0)
{
if(ch=='\n')
{
while(!(rUTRSTAT0&0x2));
//Delay(1);
WrUTXH0('\r');
}
while(!(rUTRSTAT0&0x2));
//Delay(1);
WrUTXH0(ch);
}
else
{
if(ch=='\n')
{
while(!(rUTRSTAT1&0x2));
//Delay(1);
WrUTXH1('\r');
}
while(!(rUTRSTAT1&0x2));
//Delay(1);
WrUTXH1(ch);
}
}
void myuart_send(char *str)
{
while(*str)
myuart_send_byte(*str++);
}
void Delay(U32 ms)
{
U16 i;
i = rTCNTB5>>1; //1000us/2
rTCON &= ~(1<<24);
rTCON |= (1<<24); //停止再启动,重装初值,减计数
while(ms--) {
while(rTCNTO5>=i);
while(rTCNTO5<i);
}
}
static void set_pll(void)
{
U32 i, j;
if(ClkPara.mclk>255)
ClkPara.mclk = 255;
if(ClkPara.pclk>63)
ClkPara.pclk = 63;
if(ClkPara.sclk>3)
ClkPara.sclk = 3;
j = ClkPara.sclk;
i = 1;
while(j--)
i *= 2;
ClkPara.freq = (EXT_OSC_CLK*(ClkPara.mclk+8))/((ClkPara.pclk+2)*i);
if((ClkPara.freq>=90000000)||(ClkPara.freq<EXT_OSC_CLK)) {
ClkPara.mclk = 53;
ClkPara.pclk = 3;
ClkPara.pclk = 1;
ClkPara.freq = EXT_OSC_CLK*61/10;
}
rPLLCON = (ClkPara.mclk << 12) | (ClkPara.pclk << 4) | ClkPara.sclk;
}
void SystemClockInit(void)
{
set_pll();
}
void TimerInit(U32 HZ)
{
rTCON &= ~(0xf<<24); //clear manual update bit, stop Timer5
rTCFG0 &= ~(0xff<<16); //set Timer 4&5 prescaler 1/2
rTCFG0 |= 1<<16;
rTCFG1 &= ~(0xf<<20); //set Timer 5 MUX 1/16
rTCFG1 |= 3<<20;
rTCNTB5 = GetCpuClock()/(HZ*2*16)-1;
rTCON |= 2<<24; //manual update
rTCON &= ~(2<<24); //clear manal update bit
rTCON |= (5<<24); //auto reload, inverter on, start Timer 5
}
U32 GetCpuClock(void)
{
return ClkPara.freq;
}