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

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

时间:11-11 来源:互联网 点击:

继续讨论实现中英文混输.)

嘿嘿, 我的大概框架就是这样, 当然这样的功能还是不够强大的, 对, 我们需要的是再强大一点的printf, 接下来是, 实现中英文混输, 可变参数C语言已经帮我们实现了, 也就是说我们调用printf("hello %s", str);已经能打印出hello world并且换行了, 但是如果printf("你好\n");会怎么样? 乱码? 没错, 我们现在只是实现了Ascii打印, 并没有中文, 这是与串口所不同的, 因为串口打印到电脑的超级终端, 超级终端已经帮我们实现了这个功能了, 所以printf重定向到LCD还有再封装, 对, 要更强大的函数, 实现完美的打印功能!!

中英文混输先要有一点预备知识.

1. 一个中文占两个字节, 一个Ascii占一个字节.

2. Ascii最高字节为0, 中文的两个字节最高字节都是1

上面的第二点再说明一下

如果将Ascii看成是无符号数字, 它的数值小于128, 也就是0~127

如果将中文的两个字节分别看成无符号数字, 第一个字节范围为128~255, 第二个字节也是128~255

嘿嘿, 判断中英文就有办法了~~~~

if(ch & 0x80) //判断最高位是否为1, 最高位为1表达式ch & 0x80为真

{

中文字节;

}

else

{

Ascii字节;

}

中文有两个字节, 所以要进入fputc两个才能打印出一个中文, 所以还必须把先进来的ch保存起来, 等下一个字节进来在打印,当然Ascii如果进来就直接打印. 这样我们又要有记忆功能的tmp[2]分别保存中文的两个字节了. 并且需要记录是计入的是第一个中文字节还是第二个中文字节

static uint8_t flag;

static uint8_t tmp[2];

当然, 要打印中文, 还必须有一个打印中文的函数, 我这里的函数是

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

uint8_t X 打印中文的横坐标

uint16_t Y 打印中文的纵坐标

uint8_t *Chinese 打印中文的字模

uint16_t Color 打印中文的颜色

string = Get_Chinese("好"); //获取好的字模

例如调用LCD_Chinese_One(5, 20, string, WHITE); //打印

就在LCD的位置(5, 20)打印"好", 颜色为白色

来到这里, 相信同学们都懂了吧, 啰嗦一下, 我们再来看看fputc应该怎么写

int fputc(int ch, FILE* f)

{

static uint16_t x = 0, y = 0; //坐标

uint8_t string[32]; //读取字模数组

static uint8_t flag = 0; //汉字第一第二字节标志

static uint8_t tmp[2]; //保存汉字的两个字节

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

{

x = 0;

y += 16;

return ch;

}

if(ch & 0x80) //先判断是否为中文

{

if(flag == 0) //中文的第一个字节还是第二个字节

{

flag = 1; //接下来是第二个字节

tmp[0] = ch; //记录该字节

return ch; //按照C语言的fputc需要返回ch

}

else

{

flag = 0;

tmp[1] = ch;

if(x > X_MAX - 16) //判断是否越界

{

x = 0; //换行处理

y += 16; //字模大小为16*16

}

if(y > Y_MAX - 16) //行越界

{

return ch; //直接退出处理

}

string = Get_Chinese(tmp);

LCD_Chinese_One(x, y, string, color);

x += 16;

return ch;

}

}

else

{

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;

}

}

至此, 函数封装完成了.

测试调用一下

uint8_t str = "hello world";

printf("你好, 这是一个测试程序\n%s\n", str);

在LCD上打印的是

你好, 这是一个测试程序

hello world

嘿嘿, 重定向成功了!!!

相信已经能满足广大开发者的需求了, 有待完善的地方是控制符\t\r等, 不过都是相当简单的.

下面给出我的封装, 不过我是把字模放到sdcard的, 所以需要打开文件, 读取文件等操作, 但是原理还是一样的, 嘿嘿~~~~~~

#ifdef STDOUT_LCD

int fputc(int ch, FILE* f)

{

static uint32_t Offset, Read_Count;

static uint8_t Read_Font[32];

static FRESULT File_Status;

static FIL File;

static uint16_t x = 0, y = 0;

static uint8_t flag = 0;

static uint8_t tmp[2];

File_Status = f_open(&File, CHINESE_FONT, FA_OPEN_EXISTING | FA_READ); //中文字库

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

{

x = 0; //...

y += 18; //...

return ch;

}

if(ch & 0x80) //中文处理

{

if(flag == 0) //中文的两个字节判断, flag == 0 为第一个字节

{

tmp[0] = (uint8_t)(ch); //把第一个字节保存进来

flag = 1; //接下来是第二个字节

return ch; //按照C语言官方库, 返回ch

}

else//是中文的第二个字节

{

tmp[1] = (uint8_t)(ch); //保存该字节

flag = 0

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

网站地图

Top