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


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值