在前面学习了clock设置的基础上,我们现在对uart配置。
最后达到的效果是我们可以使用printf函数来输出任意格式的数据,包括字符串等等。
第一步还是要从spec上面配置好uart的寄存器。
首先查看原理图,我们使用的是uart0。
接下来我们要设置GPH2/3为uart0端口,spec上面可以查到设置的寄存器。由于流控什么的都不需要设置,故我们只要设置uart使用的基本功能即可。这里设置bit[7:6] = 0b10, bit[5:4] = 0b10
到这里uart mode设定成功。注意:这里设置完成后要记得拉高。因为uart的协议是从拉低开始。
接下来设置波特率的一些数据参数,baudrate、stop bit,parity bit等等。
首先我们要选择uart使用的是PCLK,而PCLK配置的时候使用的是50MHz的频率。
然后波特率设置为115200,S3C2440在这里有个计算波特率的公式:
UART CLK = 50MHz,baudrate = 115200可以得到 UBRDIVn = 26.
然后需要设置我们的串口接收数据mode,可以选择polling 或者interrupt两种。
接收和发送数据都采用IR or polling mode。
然后设置数据位,停止位,校验位
到这里,我们的uart性能设置结束。接下来要设置我们的收发数据。
在状态寄存器中查询收发shift register的数据标记位是否有置位/复位。
一旦有检测到要发送或者接收的数据,立马启动发送/接收机制。
配置完成后就是上代码了:
//这里是基本的硬件配置。
/*
* brief:init GPIO, set uart mode.
* config baudrate/parity/stop bit/start bit.
* param: none
* return: none
* notice: none
*/
void uart_init(void)
{
/*init GPIO, set uart mode*/
GPHCON &= ~((3<<4) | (3<<6)); //clear bit[7:4]
GPHCON |= ((2<<4) | (2<<6)); //config bit[7:4] = 2b1010, uart mode
GPHUP &= ~((1<<2) | (1<<3)); //enable pullup
/* config baudrate:
* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
* UBRDIVn = (50000000/115200*16) - 1 = (int)26.1 = 26
*/
UCON0 = 0x5; //select interrupt or polling mode
UBRDIV0 = 26; //config badurate 115200
/*config uart data format 8N1*/
ULCON0 = 0x3;
}
/*
* brief: send data
* param: c tobe send
* return: none
* notice: none
*/
int putchar(int c)
{
/* UTRSTAT0 */
/* UTXH0 */
while(!(UTRSTAT0 & (1<<2)));
UTXH0 = (unsigned char)c;
}
/*
* brief: receive data
* param: none
* return: none
* notice: none
*/
int getchar(void)
{
/* UTRSTAT0 */
/* URXH0 */
while(!(UTRSTAT0 & (1<<0)));
return URXH0;
}
/*
* brief: send data
* param: str tobe send
* return: none
* notice: none
*/
int puts(const char *s)
{
while(*s)
{
putchar(*s);
s++;
}
}
//到这里我们开始重定向printf函数。
#include "my_printf.h"
//==================================================================================================
typedef char * va_list;
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
//#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_arg(ap,t) ( *(t *)( ap=ap + _INTSIZEOF(t), ap- _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
//==================================================================================================
unsigned char hex_tab[]={'0','1','2','3','4','5','6','7',\
'8','9','a','b','c','d','e','f'};
static int outc(int c)
{
__out_putchar(c);
return 0;
}
static int outs (const char *s)
{
while (*s != '\0')
__out_putchar(*s++);
return 0;
}
static int out_num(long n, int base,char lead,int maxwidth)
{
unsigned long m=0;
char buf[MAX_NUMBER_BYTES], *s = buf + sizeof(buf);
int count=0,i=0;
*--s = '\0';
if (n < 0){
m = -n;
}
else{
m = n;
}
do{
*--s = hex_tab[m%base];
count++;
}while ((m /= base) != 0);
if( maxwidth && count < maxwidth){
for (i=maxwidth - count; i; i--)
*--s = lead;
}
if (n < 0)
*--s = '-';
return outs(s);
}
/*reference : int vprintf(const char *format, va_list ap); */
static int my_vprintf(const char *fmt, va_list ap)
{
char lead=' ';
int maxwidth=0;
for(; *fmt != '\0'; fmt++)
{
if (*fmt != '%') {
outc(*fmt);
continue;
}
//format : %08d, %8d,%d,%u,%x,%f,%c,%s
fmt++;
if(*fmt == '0'){
lead = '0';
fmt++;
}
//For continue used %8u, code will chaos.
lead=' ';
maxwidth=0;
while(*fmt >= '0' && *fmt <= '9'){
maxwidth *=10;
maxwidth += (*fmt - '0');
fmt++;
}
switch (*fmt) {
case 'd': out_num(va_arg(ap, int), 10,lead,maxwidth); break;
case 'o': out_num(va_arg(ap, unsigned int), 8,lead,maxwidth); break;
case 'u': out_num(va_arg(ap, unsigned int), 10,lead,maxwidth); break;
case 'x': out_num(va_arg(ap, unsigned int), 16,lead,maxwidth); break;
case 'c': outc(va_arg(ap, int )); break;
case 's': outs(va_arg(ap, char *)); break;
default:
outc(*fmt);
break;
}
}
return 0;
}
//reference : int printf(const char *format, ...);
int printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
my_vprintf(fmt, ap);
va_end(ap);
return 0;
}
int my_printf_test(void)
{
printf("This is www.100ask.org my_printf test\n\r") ;
printf("test char =%c,%c\n\r", 'A','a') ;
printf("test decimal number =%d\n\r", 123456) ;
printf("test decimal number =%d\n\r", -123456) ;
printf("test hex number =0x%x\n\r", 0x55aa55aa) ;
printf("test string =%s\n\r", "www.100ask.org") ;
printf("num=%08d\n\r", 12345);
printf("num=%8d\n\r", 12345);
printf("num=0x%08x\n\r", 0x12345);
printf("num=0x%8x\n\r", 0x12345);
printf("num=0x%02x\n\r", 0x1);
printf("num=0x%2x\n\r", 0x1);
printf("num=%05d\n\r", 0x1);
printf("num=%5d\n\r", 0x1);
return 0;
}
上面是主要的程序部分,完整代码我上传到资源里面。