微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > stm32实现printf重定向到LCD显示屏

stm32实现printf重定向到LCD显示屏

时间:11-11 来源:互联网 点击:
嘿嘿,学习stm32已经有一段时间了。以前纠结过一个问题,(USART)串口的可变参数问题,查找C语言的书终于还是解决了,自己编写了一个USART_printf()函数,功能模仿C语言的printf,实现可变参数处理。有点小成就感。

我也因此发表了一下C语言可变参数的博文, 同学们有兴趣可以参考一下:

http://blog.sina.com.cn/s/blog_6e22f4ce01010uud.html

最近几天在玩LCD显示屏,基本驱动写好了,并写了一个函数支持中文英文混合打印,但是函数功能还是不够强大啊!串口的时候可以使用printf重定向,这么说开printf也可以重定向到LCD?

基于这个问题,本人昨天着手编写fputc()函数,目的是实现printf重定向到LCD。经过漫长的几个小时,调试成功了!!!调用printf("hello,%s\n", str)其中str内容是“world“;实现了在LCD上打印hello,world了。嘿嘿,后续的学习就方便很多了。

首先还是同样先复习一下printf重定向到USART,原理是修改fputc()函数,将传递进来的参数转发到USART(串口),具体fputc()函数内容编写可以参考以下例子:

int fputc(int ch, FILE* f)

{

if(ch == \n)

{

USART_SendData(USART1, \r);

USART_SendData(USART1, \n);

}

USART_SendData(USART1, (uint8_t)ch);

while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

return ch;

}

看起来很熟悉吧。但是我们现在是要把它重定向到LCD,怎么实现呢?

同样的方法,把传递进来的参数转发到LCD就行了!嘿嘿,首先要有LCD驱动,也就是有LCD打印一个字符的函数(中文是两个字节),举一个例子。假设已经有一个打印一个字符的函数

LCD_Ascii_one();

函数参数先不理,来到这一步就已经成功了一半了。像串口一样,只不过把

USART_SendData(USART1, (uint8_t)ch);

修改成

LCD_Ascii_One(...);//其中参数...中包含ch信息

这样, 整个框架就形成了, 下面是具体实现过程

先说明一下我的LCD_Ascii_One函数:

LAC_Ascii_One(uint8_t X, uint16_t Y, uint8_t *Chinese, uint16_t Color);

四个参数的含义分别为:

uint8_t X 打印字符的横坐标

uint16_t Y 打印字符的纵坐标

uint8_t *Chinese 打印字符的字模首地址 //字模提取软件得到的, 字模放在sdcard, 使用时需要打开文件

uint16_t Color 打印字符的颜色

获取字符的字模不是这里的重点, 同学们另找资料.

string = Get_Ascii(a); //获取字符a的字模

调用LCD_Ascii_One(0, 10, string, WHITE);//打印

就实现了在LCD上的位置(0, 10)打印字符a, 颜色为白色

所以fputc函数里面会有这么一句

LCD_Ascii_One(x, y, ch, color);

不过还是不够, 我们需要打印一个字符后跳到下一个位置, 不然下次打印就覆盖了本次字符了

所以还必须封装x, y, 让他们带有记忆功能, 呵呵,关键字static派上用场了

fputc函数需要声明

static uint16_t x = 0, y = 0;

为什么是uint16_t 应为我的LCD显示屏是240 * 320的

uint8_t 无法表示320, 所以是uint16_t, x也就顺便uint16_t了哈

调用玩LCD_Ascii_one之后

x += 8; //因为我提取字模是8 * 16的Ascii字模

还有一部是fputc需要的

return ch;

这样功能就完善一点了,加把劲, 继续换行功能

在调用LCD_Ascii_One()之前, 先判断x是否越界, 也就是当前这一行已经无法打印一个字符了

if(x > X_MAX - 8) //X_MAX是宏定义, 该值为240

{

x = 0; //x置零

y += 16; //y移至下一行

}

但是y也可能越界, 也就是说已经到了LCD的底部了, 我这里处理是越界直接退出, 不打印字符了

if(y > Y_MAX - 16) //Y_MAX是宏定义, 该值是320

{

return ch; //直接退出

}

换行功能还有调用printf()时候的\n

所以还是老样子, 跟串口一样:

if(ch == \n)

{

x = 0;

y += 16;

}

是否越界是上面的函数在判断.

来到这里, 我们重新再这里一下fputc的内容

需要打印一个字符自动跳到下一个位置, x越界换行, y越界退出

当然这里只是一个框架, 还有其他需要封装的, 例如中文, Ascii区分, 接下来会讨论

只是fputc至少必须包含语句:

int fputc(int ch, FILE* f)

{

static uint16_t x = 0, y = 0;

uint8_t string[16];

if(ch == \n) //换行

{

x = 0;

y += 16;

return ch;

}

if(x > X_MAX - 8) //X_MAX是宏定义, 该值为240

{

x = 0; //x置零

y += 16; //y移至下一行

}

if(y > Y_MAX - 16) //Y_MAX是宏定义, 该值是320

{

return ch; //直接退出

}

string = Get_Ascii(ch); //获取ch的字模

LCD_Ascii_One(x, y, string, color); //打印字符ch

x += 8; //跳转到下一个位置, 是否越界有上面函数判断

return ch;

}

(能够理解的同学接下来可以测试自己封装一下中英文了, 接下来我们

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top