ARM9(S3C2440) UART

来源:互联网 发布:08cms家装系统 编辑:程序博客网 时间:2024/05/22 02:17

 

                                数据通信的方式

数据通信的方式基本分为:

(1)、并行通信:多条数据线将数据的各位同属传送。

                      特点:传输速度快,适用于短距离通信。

(2)、串行通信:一条数据线将数据一位一位的顺序传送。

                      特点:线路简单,低成本,适用于远距离通信。

          一:  异步通信:

                          以一个字符为传输单位,通信中两个字符间的时间间隔是不固定的,然而同一个字符中的两个相邻位之间的时间间隔是固定的

            二: 通信协议

                          指双方约定的一些规则在异步通讯时,对数据格式有如下的约定:有空闲位,起始位,资料位,奇偶校验位,停止位。  

                          

     (1)、起始位:先发送一个逻辑信号“0”信号,表示传输字符的开始。

     (2)、数据位:紧接在起始位之后。数据位的个数可以是4,5,6,7,8等,从最低位开始传送,靠时钟定位。

     (3)、奇偶校验位:数据位加上这一位后,使得“1”的数据位应为偶数(偶校验)或奇数(奇校验),以此校验数据传送的正确性。

     (4)、停止位:他是一个字符数据的结束标志。

     (5)、空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送

 

               波特率

       衡量数据传送速率的指标:记录每秒传送的二进制位数。

       例如数据传送速率为120字符/秒,而一个字符为10位,则其传送的波特率为10*120=1200位/秒=1200波特。

 

               传送方式

 

 

 

                    UART基本原理

    Universal Asynchronous Receiver Transimitter,简称UART,通用异步收发器,它用来串行传输数据。

  发送时:CPU将数据并行写入UART,UART按照一定的格式在一根信号线上串行发送;

  接收时:UART检测另一根信号线上的信号,将串行数据放在缓冲区中,CPU可读取UART获得的这些数据。

 

                      UART驱动程序设计

 

 

 

 

 

 

         发送数据

 将要发送的数据写入UTXHn,UART会将它保存到缓冲区中,并自动发送出去。

 

        接收数据

     当UART接收到数据时(UARTSTATn寄存器bit[0]被置1,),CPU读取URXHn寄存器,即可获得数据。

 

 

实验主要代码:

main.c

/*************************************************
Function name: 这是基础实验的一个模版
Parameter    : 无
Description  : 做基础实验,直接调用该模板即可
Return      : 无
Argument     : 无
Autor & date : Daniel
**************************************************/
#define GLOBAL_CLK  1
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"


static void cal_cpu_bus_clk(void);
void Set_Clk(void);
void beep_init(void);
void beep_run(void);
/*************************************************
Function name: delay
Parameter    : times
Description  : 延时函数
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
void delay(int times)
{
    int i,j;
    for(i=0;i<times;i++)
       for(j=0;j<400;j++);
}
/*************************************************
Function name: Main
Parameter    : void
Description  : 主功能函数,实现了串口的收发功能
               首先想串口发送十次“hello world”,
               然后从键盘输入R,则蜂鸣器连续响5
               次。
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
void Main(void)

    int i;
    int Scom=0;
    Set_Clk();
    beep_init();
   
    /*设置波特率、数据位、停止位、校验位*/
    Uart_Init(0,115200);     //在2440lib.c文件中下面列出了
    //串口通道选择
    Uart_Select(Scom);
    //串口发送数据
    for(i=0;i<10;i++)
    Uart_Printf("\nHello World!\n");

    
/*************************************************
Function name: Set_Clk()
Parameter    : void
Description  : 设置CPU的时钟频率
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
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
}
/*************************************************
Function name: cal_cpu_bus_clk
Parameter    : void
Description  : 设置PCLK\HCLK\FCLK的频率
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
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;
}

/*************************************************
Function name: beep_init()
Parameter    : void
Description  : 初始化蜂鸣器
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
void beep_init(void)
{
    rGPBCON &= ~(0x3<<0);
    rGPBCON |=  (0x1<<0);
}
/*************************************************
Function name: beep_run()
Parameter    : void
Description  : 运行蜂鸣器
Return   : void
Argument     : void
Autor & date : Daniel
**************************************************/
void beep_run(void)
{
    rGPBDAT |= (0x1<<0);
    delay(5000);
    rGPBDAT &= (0x0<<0);
    delay(5000);
}

 

 

 

一些main函数中调用到的函数:

2440lib.c

....................

//***************************[ UART ]******************************
static int whichUart=0;

void Uart_Init(int pclk,int baud)
{
    int i;
    if(pclk == 0)
    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
    rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC disable
    rUMCON1 = 0x0;   //UART chaneel 1 MODEM control register, AFC disable
//UART0
    rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits
     //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
     //     0          1       0    ,     0          1        0           0     ,       01          01
     //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling
    rUCON0  = 0x245;   // Control register        1001000101
    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++);   //短暂延时
}

 

 

 

void Uart_Select(int ch)
{
    whichUart = ch;
}

 

//=====================================================================
//If you don't use vsprintf(), the code size is reduced very much.
void Uart_Printf(char *fmt,...)
{
    va_list ap;
    char string[256];

    va_start(ap,fmt);
    vsprintf(string,fmt,ap);
    Uart_SendString(string);
    va_end(ap);
}

//va_start,va_end成对出现

 

//====================================================================
void Uart_SendString(char *pt)
{
    while(*pt)
        Uart_SendByte(*pt++);
}

 

//=====================================================================
void Uart_SendByte(int data)
{
    if(whichUart==0)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT0 & 0x2));
           // Delay(1);                 //because the slow response of hyper_terminal
            WrUTXH0('\r');
        }
        while(!(rUTRSTAT0 & 0x2));   //Wait until THR is empty.
      //  Delay(1);
        WrUTXH0(data);
    }
    else if(whichUart==1)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT1 & 0x2));
            //Delay(1);                 //because the slow response of hyper_terminal
            rUTXH1 = '\r';
        }
        while(!(rUTRSTAT1 & 0x2));   //Wait until THR is empty.
        //Delay(1);
        rUTXH1 = data;
    }  
    else if(whichUart==2)
    {
        if(data=='\n')
        {
            while(!(rUTRSTAT2 & 0x2));
            //Delay(1);                 //because the slow response of hyper_terminal
            rUTXH2 = '\r';
        }
        while(!(rUTRSTAT2 & 0x2));   //Wait until THR is empty.
        //Delay(1);
        rUTXH2 = data;
    }      
}