ARM裸機串口UART

串口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++);
}


發佈了56 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章