当前位置:首页 > 单片机 > 单片机
[导读]在嵌入式软件开发过程中,往往都会用到串口进行打印信息以跟踪调试代码的运行。只要在代码的关键位置加入打印函数,即可分析代码在这一位置的关键参数是否正确,运行状态是否无误以及相关的出错信息。通过串口线连接

在嵌入式软件开发过程中,往往都会用到串口进行打印信息以跟踪调试代码的运行。只要在代码的关键位置加入打印函数,即可分析代码在这一位置的关键参数是否正确,运行状态是否无误以及相关的出错信息。通过串口线连接PC端COM口与开发板的UART即可实现开发板与PC机的通信。在代码调试阶段,开始板的状态信息通过串口打印显示在PC端屏幕,可以一目了然,是一种非常重要的调试手段。笔者此处就s3c2416的串口打印使用作一个简单的介绍。

1. UART模块实现1.1. UART初始化

在使用任何外设前,一般都是需要对外设初始化。UART也不例外,使用前需设置波特率、通信控制、通信的处理方式(中断还是查询)等。设置波特率为115200,8位数据,1位停止位,没有奇偶检验(uboot默认设置),对于慢速外设,高速cpu一般不应通过查询的方式去确定外设发送完数据或接收到数据,这会让cpu处于空等的状态,cpu效率很低,对于外设需发送或接收大量数据的情况更是如此。因此笔者此处主要讲解s3c2416串口中断方式去发送和接收数据的情况。由于s3c2416的UART发送和接收均有64字节的FIFO,通过中断的方式可以连续装载发送的数据到FIFO中或从FIFO中连续读出接收的数据,应用只需通过Uart0中断请求告知需发送或接收的数据长度及数据保存位置,即可进行等待挂起(如ucos中等待信号量标志等函数OSSemPend),cpu可转而处理其它的事情,当Uart0中断发送或接收完应用请求的所有数据,即可发送相关的信号量或标志唤醒之前等待挂起的应用(如ucos中发送信号量标志等函数OSSemPost),cpu再转而继续处理之前的应用。Uart0_Init()函数如下:

voidUart0_Init()

{

// 设置GPH0,GPH1为TX和RX

rGPHCON &= ~((3<<0)|(3<<2));

rGPHCON |= (2<<0)|(2<<2);

// 8位数据,一个停止位,没有奇偶检验

rULCON0 = 0x3;

// UART0 FIFO使能,Tx发送空时中断,Rx 16bytes中断

rUFCON0 = (0<<6) | (2<<4) | 0x7;

// 流控制禁止

rUMCON0 = 0;

// 发送接收中断使能,使用PCLK时钟66M

rUCON0 = 0x5 | (1<<7) | (2<<10);

// 设置波特率

rUBRDIV0 = 66000000/(16*Baudrate)-1;

rUDIVSLOT0 = 0x0888;

// 注册UART0 IRQ中断

IRQ_Register(INT_UART0, Uart0_IRQ);

// UART0 IRQ

rINTMOD1 &= ~(1 << INT_UART0);

// 开启RX子中断

// 在写入FIFO之前,TX必须关闭中断,不然FIFO空引发中断

rINTSUBMSK |= 0x7;

rINTSUBMSK &= ~(1 <<0);

// UART0开启中断

rINTMSK1 &= ~(1 <

}

1.2. 格式化打印函数

C语言的一些库函数功能很强大,没有必要再自己去实现。软件调试时,可能用的最多的函数就是printf。由于printf格式化输出是面向控制台的,在arm目标中是通过一种半主机的方式,把printf函数输出请求传送至运行调试器的主机。如果不对printf进行重定向是不能在目标板中使用printf等函数的(fputc和 fgetc重定向到串口或目标板屏幕)。笔者此处为了通用,不重定向改写printf,而是使用vsnprintf函数进行格式化输出到字符串中,再把字符串发送到串口,实现与printf类似的串口打印输出。串口格式化打印函数Uart0_Printf()如下:

// 串口打印函数,替换库函数printf函数功能

// printf是向控制台输出信息,通过vsnprintf格式化数据输出

// 到字符串,并通过串口发送字符串函数进行串口打印

voidUart0_Printf(char *fmt, ...)

{

va_list ap;

char String[1024];

va_start(ap, fmt);

vsnprintf(String, sizeof(String), fmt, ap);

va_end(ap);

Uart0_SendString(String);

}

1.3. 串口字符串输出

Uart0_Printf()通过vsnprintf()格式化输出到字符串后,即可用Uart0_SendString()进行字符串发送,Uart0_SendString()会确定出字符串的长度,即确定串口发送的数据长度,再调用Uart0_SendData()进行发送一定长度的字节数据到串口。

// 通过串口发送字符串

voidUart0_SendString(char *String)

{

unsigned int Len;

char *Temp = String;

if (String == 0) {

return;

}

Len = 0;

// 获得字符串的长度

while (*Temp++) {

Len++;

}

Uart0_SendData((unsigned char *)String,Len);

}

1.4. 任意长度字节输出

Uart0_SendData()会最终向uart0请求发送一定长度的数据,以及数据所在的位置,之后会进入等待,直到uart0中断发送完所有请求的数据。由于Uart对外发送数据是很慢的,如果有操作系统或状态机实现中,在while等待中,可改成类似信号量等待,把Uart0_SendData()函数挂起(如OSSemPend(ucos)),直到uart0中断完成请求后,发送信号量或标志再唤醒执行(如OSSemPost(ucos))。Uart0_SendData()函数实现如下:

// 通过串口发送任意长度的数据

voidUart0_SendData(unsigned char *pBuffer, unsigned int Len)

{

if (pBuffer == 0 || Len == 0) {

return;

}

TxLen = Len; // 向中断请求发送的数据字节长度

pTxData = pBuffer; // 发送数据的位置

TxLen--; // 发送了一字节,发送数据长度减1

// 发送第一个字节完后会产生中断,之后数据在中断函数中连续发送

rUTXH0 = *pTxData++;

rINTSUBMSK &= ~(1 <<1); // 数据写入FIFO后开启TX发送完中断

while(TxLen != -1) {

// 等待UART0数据发送完

// 可改成操作系统信号量等待函数,提高cpu效率,如OSSemPend(ucos)

}

}

1.5. 发送字节函数

Uart0_SendByte()用来向串口发送一字节的数据(字符),其向uart0请求一字节的数据发送。

// 通过串口发送一字节数据

voidUart0_SendByte(unsigned char Byte)

{

TxLen = 0; // 发送1字节后,发送数据长度为0

rUTXH0 = Byte; // 1字节数据装载进FIFO中

rINTSUBMSK &= ~(1 <<1); // 数据写入FIFO后开启TX中断

while (TxLen != -1) { // 等待中断中发送完标志

// 等待UART0数据发送完

// 可改成操作系统信号量等待函数,提高cpu效率,如OSSemPend(ucos)

}

}

1.6. 字符串接收函数

Uart0_ReceiveString()用来请求通过串口接收字符串,其会调用Uart0_ReceiveByte()来向uart0请求接收一个字节的数据,根据接收到的字符数据判断是否字符串结束或者回车结束。

// 通过串口接收字符串,指定缓存长度为Len

voidUart0_ReceiveString(char *pBuffer, unsigned int Len)

{

char *Temp;

unsigned int i;

if (pBuffer == 0 || Len == 0) {

return;

}

Temp = pBuffer;

for (i=0; i

*Temp = Uart0_ReceiveByte();

if (*Temp == 0 || *Temp == 'r') {

break; // 字符串结束或回车则结束输入

}

Temp++;

}

if (i < Len) {

pBuffer[i] = 0; // 字符串末尾加入结束字符0

} else {

pBuffer[Len-1] = 0;

}

}

1.7. 字节接收函数

Uart0_ReceiveByte()会通过uart0请求接收一个字节的数据,阻塞直到接收到数据返回。

// 通过串口接收一字节数据

charUart0_ReceiveByte(void)

{

unsigned char Value;

pRxData = &Value; // 中断中接收的1字节数据放在Value中

RxLen = 1; // 接收长度为1字节

while(RxLen != 0) {

// 等待UART0数据接收

// 可改成操作系统信号量等待函数,提高cpu效率,如OSSemPend(ucos)

}

return ((char)Value);

}

1.8. 中断请求处理

Uart0_IRQ()中断处理函数用来处理应用的发送请求以及接收请求。如果请求的发送数据长度或请求的接收数据长度过大,将会分多个中断请求来分包发送数据或接收数据,直到所有的数据请求均完成后,通过发送信号量(如OSSemPost(ucos))或完成标志告知请求的应用。

// 请求通过串口发送的字节数

static volatile int TxLen = 0;

// 请求通过串口接收的

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

IIC是Philips推出的芯片间串行传输总线,它以二根连线实现完善的全双工同步数据传送,可以极方便地构成多机系统和外围器件扩展系统。由于其接口简单灵活,很多外围器件均提供了IIC接口,如手机、平板常用的重力传感器

关键字: s3c2416 裸机开发 iic驱动

现在主要讲解一下在GCC移植UCGUI,Makefile工程如何加入目录,加入源码,c标准库,编译选项的设置。笔者的Makefile模板提取自uboot,工程中加入目录,加入源码都是很简单的,详细的介绍请参考前面章节”...

关键字: gcc s3c2416 ucgui 移植 裸机开发

jpeg格式是一种针对相片影像而广泛使用的一种失真压缩标准,其压缩技术十分先进,用有损压缩方式去除冗余的图像数据,在获得极高压缩率的同时,能展现十分丰富生动的图像,能用最少的磁盘空间得到较好的图像品质。由

关键字: s3c2416 移植 裸机开发 libjpeg

在消费电子产品中,往往都会用到音频系统来播放音乐、进行通话等多媒体应用,此外,对于一些需语音提示的产品,音频部分都是不可或缺的功能。笔者此处就s3c2416的音频驱动实现作一个简单的介绍。1. IIS音频总线s3c24

关键字: s3c2416 裸机开发 音频驱动

S3C2416裸机开发系列十八_音频驱动实现(2)标签:WM8960IIS音频驱动s3c2416裸机开发2014-06-10 09:50853人阅读评论(0)收藏举报分类:s3c2416裸机开发(24)版权声明:本文为博...

关键字: s3c2416 裸机开发 音频驱动

很多的嵌入式系统都需要人机交互,对于输出设备,LCD以其显示质量高、画面效果好等优点得到了极其广泛的应用。s3c2416包含了一个LCD控制器,笔者此处就s3c2416的LCD应用作一个简单的介绍。1、LCD控制器概述1...

关键字: s3c2416 裸机开发 rgb屏 驱动显示

在嵌入式设计中,由于Nand Flash具有大容量,擦写次数高,接口简单等优点,常用作固化存储器。S3C2416支持Nand启动,因此Nand存储器可以直接保存固化代码以及其它的数据。笔者在此简单的介绍Nand flas...

关键字: nand驱动 s3c2416 裸机开发 nand启动

笔者前面章节简单介绍了s3c2416启动代码的实现过程,启动代码就是用来处理cpu体系结构中一些底层内容,一个功能强大的启动代码是可以当作bootloader(如uboot)来用的。有了启动代码,用户就可以专注于用c来作...

关键字: mdk s3c2416 启动代码 裸机开发

启动代码是处理器上电复位后最先运行的一段代码。主要是用来把处理器初始化到一个确定的状态,为c运行环境作好准备。如设置异常向量表,初始化系统时钟,初始化外部内存,把用户代码拷贝到外部内存,初始化栈,清0全

关键字: s3c2416 启动代码 流水灯 裸机开发

S3C2416裸机开发系列十九_Fatfs下播放录音wav音频文件标签:wavfatfs音频播放s3c2416sd驱动2014-06-11 09:551938人阅读评论(0)收藏举报分类:s3c2416裸机开发(24)版...

关键字: s3c2416 裸机开发 播放录音 音频文件
关闭
关闭