串口UART原理
異步通信:傳輸單位是一個字符,兩個字符之間時間間隔不固定,時間固定爲同步。
通信協議:通信雙方共同制定的規則,有數據格式:奇偶校驗位、停止位.....,通信流程上的規格.
UART(universal asynchronous receivertransmitter):通用異步收發器,用來串行傳輸數據,發送時,CPU將數據並行寫入UART,UART按照一定格式在一位的數據線上串行發送,接受時,從一位數據線接受串行的數據。
S3c2440有三個獨立的uart接口,並且每個uart包括64字節的接受和發送fifo。
串口基本工作原理:分爲發送和接收部分,發送部分:1接口用來接收數據,數據由CPU通過BUS送到uart,首先進入transmitbuffer,然後會自動的把每字節送入transmitshift把8位數據依位移出發送,發送過程受波特率控制每秒發送位數。接收:從數據依位收到放入 receive shift形成一個字節,放入buffer,通過機制(中斷)告訴CPU,完成接受。
串口UART程序設計
UART初始化:設置波特率-->設置串口數據傳輸格式-->選擇通道工作模式(DMA,中斷......)。
1:通過UART Baud Rate Divisor Register即UBRDIV可以設置UART波特率,波特率的設置依賴一個公式 UBRDIV=(int)(uartclock / (baud rate * 16) ) -1
(uart clock :PCLK or FCLK /n or UEXTCLK)
CPU一工作clock就定下來,設置波特率就是設置UBRDIV。
2:設置傳輸格式,通過UART LINE CONTROL REGISTER即ULCON,可以設置傳輸格式。
3:設置通道工作模式:通過UART CONTROL REGISTER,即UCON。
完成初始化後發送數據
把要發送的數據寫入UTXHn(4個字節),UART會把它保存到緩衝區,並自動發送。
接收數據:一旦接收到數據之後,如果沒有DMA和中斷,可以查詢UTRSTATn寄存器的第0位,從URXHn寄存器拿數據。
串口發送數據程序:
static void cal_cpu_bus_clk(void);
void Set_Clk(void);
void beep_init(void);
void beep_run(void);
void delay(int times) {
int i,j;
for(i=0;i<times;i++)
for(j=0;j<400;j++);
}
void Main(void) {
int i;
int Scom=0;
Set_Clk(); //設置時鐘
beep_init();
/*串口初始化設置波特率、數據位、停止位、校驗位*/
Uart_Init(0,115200);
Uart_Select(Scom); //串口通信選擇
for(i=0;i<10;i++) //串口發送數據
Uart_Printf("\nHello World!\n");//串口輸出的數據
}
void Set_Clk(void)
{
int i;
U8 key;
U32 mpll_val = 0 ;
i = 2 ; //don't use 100M!
//boot_params.cpu_clk.val = 3;
switch ( i ) {
case 0: //200
key = 12;
mpll_val = (92<<12)|(4<<4)|(1);
break;
case 1: //300
key = 13;
mpll_val = (67<<12)|(1<<4)|(1);
break;
case 2: //400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3: //440!!!
key = 14;
mpll_val = (102<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
//init FCLK=400M, so change MPLL first
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCON
ChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bit
cal_cpu_bus_clk(); //HCLK=100M PCLK=50M
}
/
static void cal_cpu_bus_clk(void)
{
static U32 cpu_freq;
static U32 UPLL;
U32 val;
U8 m, p, s;
val = rMPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
//(m+8)*FIN*2 不要超出32位數!
FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //FCLK=400M FIN=12000000
val = rCLKDIVN;
m = (val>>1)&3;
p = val&1;
val = rCAMDIVN;
s = val>>8;
switch (m) {
case 0:
HCLK = FCLK;
break;
case 1:
HCLK = FCLK>>1;
break;
case 2:
if(s&2)
HCLK = FCLK>>3;
else
HCLK = FCLK>>2;
break;
case 3:
if(s&1)
HCLK = FCLK/6;
else
HCLK = FCLK/3;
break;
}
if(p)
PCLK = HCLK>>1;
else
PCLK = HCLK;
if(s&0x10)
cpu_freq = HCLK;
else
cpu_freq = FCLK;
val = rUPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}
void beep_init(void)
{
rGPBCON &= ~(0x3<<0);
rGPBCON |= (0x1<<0);
}
void beep_run(void)
{
rGPBDAT |= (0x1<<0);
delay(5000);
rGPBDAT &= (0x0<<0);
delay(5000);
}
void Uart_Init(int pclk,int baud)
{
int i;
if(pclk == 0)
pclk = PCLK; //串口使用PCLK
rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable
rUFCON1 = 0x0; //UART channel 1 FIFO control register, FIFO disable
rUFCON2 = 0x0; //UART channel 2 FIFO control register, FIFO disable//關掉fifo
rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable
rUMCON1 = 0x0; //UART chaneel 1 MODEM control register, AFC disable rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits
rUCON0 = 0x245; // Control register
rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0
//UART1
rULCON1 = 0x3;
rUCON1 = 0x245;
rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 );
//UART2
rULCON2 = 0x3;
rUCON2 = 0x245;
rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );
for(i=0;i<100;i++);
}