JZ2440裸板开发练习#4 串口UART

预备知识

硬件

RS232电平:负逻辑电压(负电平表示逻辑1,正电压表示逻辑0),12v,电脑使用居多

TTL/CMOS电平:正逻辑电压(正负电压分别表示逻辑1和0),5v,单片机等嵌入式设备使用较多

(RS232多为9孔插槽,TTL/CMOS电平设备需要使用转换芯片才能与RS232电平设备通信,一般该芯片集成到嵌入式设备中,以9孔232插槽作为硬件端口,但是现在使用变少,慢慢由USB取代,因此需要的芯片变为TTL/CMOS转USB芯片)

TXD、RXD、GND:TXD为发送引脚,RXD为接收引脚,发送端和接受端的TX和RX应该以RX-TX的连接方式连接。GND用于设备共地,保证逻辑电平的一致(电势有参考才能以电压论述)。

软件

数据格式:起始位,数据位,校验位,停止位

串口协议数据异步传输协议,每一次传输需要由额外的信息来发起一次传输同步。通常这种同步格式以起始位和停止位来体现。同时为了保证数据的正确性,串口协议还可以存在校验位来判断本次传输的数据是否正确,一般常用为奇偶校验,也可以有其他方式校验。剩下的几位数据位。

串口协议空闲情况下TXD和RXD被上拉电阻拉高,体现为高电平,当从高电平置为低电平,则视为一个起始位( 0 ),而停止位则为相反的从低电平转为高电平( 1 )。一般情况下,使用的是8n1,即8个数据位,1个起始位和1个停止位,没有校验位,即发送1Byte数据需要发送10bits发送。

波特率:接收端和发送端协商好的发送数据的速率,含义为1s内发送的数据位数。

分析

以S3C2440的串口框图为例,需要发送数据时,数据将从内存中通过外设总线传入TransmitBufferRegister即传输缓存寄存器中,然后发送移位寄存器会将缓冲区中待发送的数据逐位发送。接收则是通过接收移位寄存器将接收到的数据逐位保存到缓冲区中,等待提取。移位寄存器的速率受波特率发生器影响,这个就是上文中提到的我们需要提前订好的发送或者接收速率,需要发送端和接收端都一致才能保证信息的正确性。

 

程序

和往常一样,需要使用到一样功能,需要看原理图找到相应的引脚,然后查找寄存器,配置寄存器,使能功能,再加上业务逻辑完成期望功能。原理图中看出板载有USB转uart的电路,连接的是TXD0和RXD0,分别连接到GPH2和GPH3引脚,因此需要将这两个引脚的UART功能使能,再配置uart的相关寄存器。

扫描二维码关注公众号,回复: 9846234 查看本文章

 

 将uart需要用到的寄存器添加到s3c2440.h中,方便以后复用。

s3c2440.h
--------------------------------------------------------------
#ifndef __S3C2440_H
#define __S3C2440_H

#include <stdint.h>

/* CLOCK --------------------------------------------------*/
#define MPLLCON	 (*((volatile uint32_t*)0x4C000004))
#define UPLLCON	 (*((volatile uint32_t*)0x4C000008))

#define CLKDIVN	(*((volatile uint32_t*)0x4C000014))


/* WATCH DOG --------------------------------------------------*/
#define WTCON	(*((volatile uint32_t*)0x53000000))

/* GPIO --------------------------------------------------*/
#define GPGCON	(*((volatile uint32_t*)0x56000060))
#define GPGDAT	(*((volatile uint32_t*)0x56000064))
#define GPGUP	(*((volatile uint32_t*)0x56000068))

#define GPFCON	(*((volatile uint32_t*)0x56000050))
#define GPFDAT	(*((volatile uint32_t*)0x56000054))
#define GPFUP	(*((volatile uint32_t*)0x56000058))

#define GPHCON	(*((volatile uint32_t*)0x56000070))
#define GPHDAT	(*((volatile uint32_t*)0x56000074))
#define GPHUP	(*((volatile uint32_t*)0x56000078))

/* UART --------------------------------------------------*/
//uart0
#define ULCON0	(*((volatile uint32_t*)0x50000000))
#define UCON0	(*((volatile uint32_t*)0x50000004))
#define UFCON0	(*((volatile uint32_t*)0x50000008))
#define UMCON0	(*((volatile uint32_t*)0x5000000C))
#define UTRSTAT0	(*((volatile uint32_t*)0x50000010))
#define UERSTAT0	(*((volatile uint32_t*)0x50000014))
#define UFSTAT0	(*((volatile uint32_t*)0x50000018))
#define UMSTAT0	(*((volatile uint32_t*)0x5000001C))
#define UBRDIV0	(*((volatile uint32_t*)0x50000028))

#define UTXH0 (*((volatile uint8_t*)0x50000020))
#define URXH0 (*((volatile uint8_t*)0x50000024))

//uart1
#define ULCON1	(*((volatile uint32_t*)0x50004000))
#define UCON1	(*((volatile uint32_t*)0x50004004))
#define UFCON1	(*((volatile uint32_t*)0x50004008))
#define UMCON1	(*((volatile uint32_t*)0x5000400C))
#define UTRSTAT1	(*((volatile uint32_t*)0x50004010))
#define UERSTAT1	(*((volatile uint32_t*)0x50004014))
#define UFSTAT1	(*((volatile uint32_t*)0x50004018))
#define UMSTAT1	(*((volatile uint32_t*)0x5000401C))
#define UBRDIV1	(*((volatile uint32_t*)0x50004028))

#define UTXH1 (*((volatile uint8_t*)0x50004020))
#define URXH1 (*((volatile uint8_t*)0x50004024))

//uart2
#define ULCON2	(*((volatile uint32_t*)0x50008000))
#define UCON2	(*((volatile uint32_t*)0x50008004))
#define UTRSTAT2	(*((volatile uint32_t*)0x50008010))
#define UERSTAT2	(*((volatile uint32_t*)0x50008014))
#define UFSTAT2	(*((volatile uint32_t*)0x50008018))
#define UBRDIV2	(*((volatile uint32_t*)0x50008028))

#define UTXH2 (*((volatile uint8_t*)0x50004020))
#define URXH2 (*((volatile uint8_t*)0x50008024))


void HardwareInitAll(void);
void Delay(uint32_t time);

#endif

配置GPIO为RXD和TXD功能,并配置UART相关寄存器,将uart的通信设置为8位数据位,无校验位,1位停止位,使用PCLK(50MHz)作为uart时钟,并由波特率为115200代入参考手册提供的公式,得到uart时钟分频。如下:

uart.h
----------------------------------------------------
#ifndef __UART_H
#define __UART_H

#include <stdint.h>

void UartInit(void);

void putc(uint8_t character);
uint8_t getc(void);

#endif
uart.c
------------------------------------------

#include "uart.h"


#include "s3c2440.h"


void UartInit(void)
{
	//GPIO init
	GPHCON &= ~((3<<6) | (3<<4));
	GPHCON |= (2<<6) | (2<<4);

	//UART init
	ULCON0 = 3;  //8n1
	UCON0 = (1<<2) | (1<<0);
	UBRDIV0 = (int32_t)( 50000000/ (115200 * 16) ) -1;
}


static uint8_t IsReadyToSend(void)
{
	return UTRSTAT0 & (1<<1);
}


static uint8_t IsReadyToReceive(void)
{
	return UTRSTAT0 & (1<<0);
}

void putc(uint8_t character)
{
	while(!IsReadyToSend());
	UTXH0 = character;
	if(character==(uint8_t)('\r'))
	{
		while(!IsReadyToSend());
		UTXH0 = (uint8_t)'\n';
	}
}

uint8_t getc(void)
{
	while(!IsReadyToReceive());
	return URXH0;
}

同时将状态寄存器中的相关状态位封装成指定功能的函数,增加需要的逻辑,得到最终的业务代码:putc和getc,效果为,使用串口工具进行通信,输入字符即可回显。

main.c
--------------------------------------------

#include <stdint.h>

#include "s3c2440.h"
#include "led.h"
#include "uart.h"

int main()
{
	HardwareInitAll();
	UartInit();
	
	uint8_t tmp;

	while(1)
	{
		tmp = getc();
		putc(tmp);
	}
}

至此,一个简单粗糙的串口回显程序完成。

发布了19 篇原创文章 · 获赞 7 · 访问量 6925

猜你喜欢

转载自blog.csdn.net/G_METHOD/article/details/104288739