裸板开发_bootloader_开发之路(四)写一个自己的串口

目录

  • 一、目的:
  • 二、串口简介:
  • 二、看芯片手册写:
    • 2.1、s3c2440总共有三组串口:
    • 2.2、波特率设置
  • 三、写代码
    • 3.1、初始化GPIO管脚
    • 3.2、初始化串口:
    • 3.3、配置串口:
    • 3.4、写输出函数:
    • 3.5、写读取函数:
    • 3.6、主函数中测试
  • 四、完整代码:
  • 五、后记

声明:本文章基于韦东山的教程所写,为学习时的笔记和问题记录。

一、目的:

  • 看芯片手册,熟悉串口
  • 写一个串口输入和输出

二、串口简介:

  • 串口英文名称为:通用异步接受发送器。
  • 硬件上面,一根tx.一根rx线

二、看芯片手册写:

2.1、s3c2440总共有三组串口:

裸板开发_bootloader_开发之路(四)写一个自己的串口_第1张图片

2.2、波特率设置

  • 比特率是UART传输时,双方约定的传输速率:
  • 这是芯片手册里面的设置方法裸板开发_bootloader_开发之路(四)写一个自己的串口_第2张图片
//注意常用波特率为115200
	/* 设置波特率 */
	/* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
	 *  UART clock = 50M
	 *  UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
	 */
	UBRDIV0 = 26;

三、写代码

3.1、初始化GPIO管脚

	/* 设置引脚用于串口 */
	/* GPH2,3用于TxD0, RxD0 */
	GPHCON &= ~((3<<4) | (3<<6));
	GPHCON |= ((2<<4) | (2<<6));
	
	//上拉管脚避免干扰
	GPHUP &= ~((1<<2) | (1<<3));  /* 使能内部上拉 */

3.2、初始化串口:

	UCON0 = 0x00000005; /* PCLK,中断/查询模式 */

3.3、配置串口:

8个数据位,无校验位,1个停止位是默认配置

	/* 设置数据格式 */
	ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 */

3.4、写输出函数:

void putchar(char c)
{
	/* UTRSTAT0 */
	/* UTXH0 */
	//如果状态寄存器不为占用
	while (!(UTRSTAT0 & (1<<2)));
	//发送数据
	//UTXH0 这个为uart发送buffer寄存器,我们只需要将数据填入就可以啦
	UTXH0 = (unsigned char)c;
}

3.5、写读取函数:

int getchar()
{
//当没有获取数据时,死循环
	while (!(UTRSTAT0 & (1<<0)));
//获取到数据就返回这个值
	return URXH0;
}

3.6、主函数中测试

int main(void)
{
	unsigned char c;
	
	uart0_init();
	puts("Hello, world!\n\r");
	
	while(1)
	{
		c = getchar();
		
		//在不同的环境中,换行符表示不一样,操作是为了保证一定换行 
		if (c == '\r')
		{
			putchar('\n');
		}

		if (c == '\n')
		{
			putchar('\r');
		}
		//打印接受的数据
		putchar(c);
	}
	return 0;
}

四、完整代码:

  1. uart.c

#include "s3c2440_soc.h"


/* 115200,8n1 */
void uart0_init()
{
	/* 设置引脚用于串口 */
	/* GPH2,3用于TxD0, RxD0 */
	GPHCON &= ~((3<<4) | (3<<6));
	GPHCON |= ((2<<4) | (2<<6));

	GPHUP &= ~((1<<2) | (1<<3));  /* 使能内部上拉 */
	

	/* 设置波特率 */
	/* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
	 *  UART clock = 50M
	 *  UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
	 */
	UCON0 = 0x00000005; /* PCLK,中断/查询模式 */
	UBRDIV0 = 26;

	/* 设置数据格式 */
	ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 */

	/*  */

}

int putchar(int c)
{
	/* UTRSTAT0 */
	/* UTXH0 */

	while (!(UTRSTAT0 & (1<<2)));
	UTXH0 = (unsigned char)c;
	
}

int getchar(void)
{
	while (!(UTRSTAT0 & (1<<0)));
	return URXH0;
}

int puts(const char *s)
{
	while (*s)
	{
		putchar(*s);
		s++;
	}
}

2.main.c

#include "s3c2440_soc.h"
#include "uart.h"

int main(void)
{
	unsigned char c;
	
	uart0_init();
	puts("Hello, world!\n\r");
	
	while(1)
	{
		c = getchar();
		if (c == '\r')
		{
			putchar('\n');
		}

		if (c == '\n')
		{
			putchar('\r');
		}

		putchar(c);
	}
	return 0;
}

五、后记

  • 在以前使用单片机的时候,往往只会用别人提供好的库函数来操作串口,这样当然方便快捷,但是封装的同时也必然意味着一个问题,那就是隐藏了很多的操作以及信息,对于只需要串口的接受和打印固然是足够的,但是一旦要进行深度的操作和解决疑难问题,那么不了解底层的操作是远远不够的。

你可能感兴趣的:(bootloader)