本帖最后由 51xlf 于 2022-7-1 17:40 编辑
#申请原创# @21小跑堂 近期又购置了一个arduino接口的TFT LCD,可以兼容arduino接口。而且芯片还自动SD卡,后期可以通过这个SD卡加载汉字库。
需要在arduino上测试了一下,感觉效果还是可以的。突然想起来,AT-START-F425的板子也是自带arduino的接口的。
这个板子可以完全和AT-START-F425板子完美的融合起来的。奔着说干就干的原则,先看看需要用到哪些接口?
屏幕的接口就是暂时用到的是绿色框中的几个引脚。
而对应在屏幕上的几个端,就需要看原理图了。完美的arduino的接口,不错。
看一下屏幕和AT-START-F425的契合的图片。
就是刷新的速度有限,不能发挥出AT32F425的能力,不过这个的速度还是可以的。
这个需要用到的几个引脚。先在程序里面配置一下,因为不是连续的引脚,所以这个只能是按照位进行操作了。
程序的配置有点繁琐了,不如直接给寄存器赋值来的直接。先把引脚全部的配置为输出了。
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
/* set default parameter */
gpio_default_para_init(&gpio_init_struct);
/* configure button pin as input with pull-up/pull-down */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_0 |GPIO_PINS_1|GPIO_PINS_4|GPIO_PINS_8|GPIO_PINS_9|GPIO_PINS_10;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_0 |GPIO_PINS_4|GPIO_PINS_3|GPIO_PINS_5|GPIO_PINS_10;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init(GPIOB, &gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_1 |GPIO_PINS_7;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
gpio_init(GPIOC, &gpio_init_struct);
后面就是对IO口进行赋值操作了,习惯了使用了stm32的HAL了,所以这里还是使用的宏定义对LCD的控制引脚(例如复位 读写 片选)进行操作的,
这样好操作,而且后期移植到其他的程序上也是非常的方便的。
#define LCD_RD_GPIO_Port GPIOA
#define LCD_RD_Pin GPIO_PINS_0
#define LCD_WR_GPIO_Port GPIOA
#define LCD_WR_Pin GPIO_PINS_1
#define LCD_RS_GPIO_Port GPIOA
#define LCD_RS_Pin GPIO_PINS_4
#define LCD_CS_GPIO_Port GPIOB
#define LCD_CS_Pin GPIO_PINS_0
#define LCD_RST_GPIO_Port GPIOC
#define LCD_RST_Pin GPIO_PINS_1
#define LCD_D0_GPIO_Port GPIOA
#define LCD_D0_Pin GPIO_PINS_9
#define LCD_D1_GPIO_Port GPIOC
#define LCD_D1_Pin GPIO_PINS_7
#define LCD_D2_GPIO_Port GPIOA
#define LCD_D2_Pin GPIO_PINS_10
#define LCD_D3_GPIO_Port GPIOB
#define LCD_D3_Pin GPIO_PINS_3
#define LCD_D4_GPIO_Port GPIOB
#define LCD_D4_Pin GPIO_PINS_5
#define LCD_D5_GPIO_Port GPIOB
#define LCD_D5_Pin GPIO_PINS_4
#define LCD_D6_GPIO_Port GPIOB
#define LCD_D6_Pin GPIO_PINS_10
#define LCD_D7_GPIO_Port GPIOA
#define LCD_D7_Pin GPIO_PINS_8
#define LCD_CS_LOW() LCD_CS_GPIO_Port->clr =LCD_CS_Pin //
#define LCD_CS_HIGH() LCD_CS_GPIO_Port->scr = LCD_CS_Pin //
#define LCD_RST_LOW() LCD_RST_GPIO_Port->clr = LCD_RST_Pin //
#define LCD_RST_HIGH() LCD_RST_GPIO_Port->scr = LCD_RST_Pin //
这里需要对屏幕进行操作了,需要用到的按照位进行操作了。
使用右键查询到使用寄存器赋值的方法。
对IO进行赋值需要对scr进行操作,如果是需要置0则对clr进行操作。
具体的代码如下所示,保障了屏幕的刷新速度了。最快的实现置位和置0的操作。
LCD_WR_GPIO_Port->clr = (uint32_t)LCD_WR_Pin ;
if(dat&0x01) LCD_D0_GPIO_Port->scr = (uint32_t)LCD_D0_Pin;
else LCD_D0_GPIO_Port->clr = (uint32_t)LCD_D0_Pin ;
if(dat&0x02) LCD_D1_GPIO_Port->scr = (uint32_t)LCD_D1_Pin;
else LCD_D1_GPIO_Port->clr = (uint32_t)LCD_D1_Pin ;
if(dat&0x04) LCD_D2_GPIO_Port->scr = (uint32_t)LCD_D2_Pin;
else LCD_D2_GPIO_Port->clr = (uint32_t)LCD_D2_Pin;
if(dat&0x08) LCD_D3_GPIO_Port->scr = (uint32_t)LCD_D3_Pin;
else LCD_D3_GPIO_Port->clr = (uint32_t)LCD_D3_Pin;
if(dat&0x10) LCD_D4_GPIO_Port->scr = (uint32_t)LCD_D4_Pin;
else LCD_D4_GPIO_Port->clr = (uint32_t)LCD_D4_Pin ;
if(dat&0x20) LCD_D5_GPIO_Port->scr = (uint32_t)LCD_D5_Pin;
else LCD_D5_GPIO_Port->clr = (uint32_t)LCD_D5_Pin ;
if(dat&0x40) LCD_D6_GPIO_Port->scr = (uint32_t)LCD_D6_Pin;
else LCD_D6_GPIO_Port->clr = (uint32_t)LCD_D6_Pin ;
if(dat&0x80) LCD_D7_GPIO_Port->scr = (uint32_t)LCD_D7_Pin;
else LCD_D7_GPIO_Port->clr = (uint32_t)LCD_D7_Pin ;
LCD_WR_GPIO_Port->scr = (uint32_t)LCD_WR_Pin;
具体怎么配置寄存器,这里就不再赘述了。就是跟配置正常的LCD一样了,主要的实现对数据寄存器的写入。
再根据需要配置的形式,自己实现数据和命令的控制,这个具体的代码,在购买屏幕的时候,他就直接给出了。
自己根据提供的例程,选择一下,自己要实现的方式就行了。屏幕的配置很简单,都是固定的代码。
主要的实现函数就是现实一个点的绘制,点动成线,线动成面。
这样就会绘制出来想要的效果了。这个代码使用的就是淘宝店家的提供的例程了。
void lcd_point(uint16_t x, uint16_t y,uint16_t color){
if ((x >= LCD_W) || (y >= LCD_H)) return ;
LCD_CS_LOW(); //HAL_GPIO_WritePin(LCD_CS,LOW);
lcd_address_set(x, y, x, y);
lcd_write_data(color >> 8);
lcd_write_data(color);
LCD_CS_HIGH(); //HAL_GPIO_WritePin(LCD_CS,HIGH);
}
有了这个点,后面就是现实的文字输出,根据自己的字库实现字符和汉字的输出了
字符很简单,就是根据字模输出屏幕了就行了。
这里移植了一个oled的显示程序,里面很简单,可以根据自己的需要选择需要的字符。具体的字库,可以看后面的代码了。
这个代码做的就是非常好,可选择性很高。
u8 i,m,temp,size2,chr1;
u8 x0=x,y0=y;
if(size1==8)size2=6;
else size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' '; //计算偏移后的值
for(i=0; i<size2; i++)
{
if(size1==8)
{
temp=asc2_0806[chr1][i]; //调用0806字体
}
else if(size1==12)
{
temp=asc2_1206[chr1][i]; //调用1206字体
}
else if(size1==16)
{
temp=asc2_1608[chr1][i]; //调用1608字体
}
else if(size1==24)
{
temp=asc2_2412[chr1][i]; //调用2412字体
}
else return;
for(m=0; m<8; m++)
{
if(temp&0x01)lcd_point(x,y,f_color);
else lcd_point(x,y,b_color);
temp>>=1;
y++;
}
x++;
if((size1!=8)&&((x-x0)==size1/2))
{
x=x0;
y0=y0+8;
}
y=y0;
}
至于字符串就是逐个对字符进行输出实现。
这里说明一下如何实现汉字的输出。参考正点原子的方法。
实现字符的取模用的是PC2LCD2000,因为软件的原因,获取的数据,需要修改的内容很多,太麻烦,所以我将正点原子的变量修改了一下,
这样就可以直接实现把内容复制到字模文件中了。
struct typFNT_GB162
{char Msk[32];
unsigned char Index[2];
unsigned char no;
};
这样对比一下就行了,直接复制粘贴的效果还是比较好的。省去了,调换字符位置,删除字符内容等一系列的复杂操作。
接下来实现的就是汉字和字符的混合输出了。
根据字符的大小判断是字符还是汉字,如果是字符调用上述的方法就可以实现,如果是汉字,就根据汉字字模,赋值前景色和背景色就行了。
while(*chr) {
if((*chr) < 128)
{
OLED_ShowChar(x,y,*chr,size1, f_color,b_color);
if(size1==8)x+=6;
else x+=size1/2;
chr++;
} else {
for (k=0; k<hz16_num; k++)
{
if ((hz16[k].Index[0]==*(chr))&&(hz16[k].Index[1]==*(chr+1)))
{
for(i=0; i<16; i++)
{
for(j=0; j<8; j++)
{
if(hz16[k].Msk[i*2]&(0x80>>j)) lcd_point(x+j,y+i,f_color);//lcd_point(x,y,f_color);
else {
lcd_point(x+j,y+i,b_color);
}
}
for(j=0; j<8; j++)
{
if(hz16[k].Msk[i*2+1]&(0x80>>j)) lcd_point(x+j+8,y+i,f_color);//lcd_point(x+j,y+i,f_color);
else
{
lcd_point(x+j+8,y+i,b_color);
}
}
}
}
}
chr+=2;
x+=16;
}
}
主要的一些代码已经实现了
OLED_ShowStringCN(0,20,"bbs.21ic.com",16,GREEN,BLACK);
OLED_ShowStringCN(0,40,"雅特力AT32 MCU",16,RED,BLACK);
lcd_show_image(0,60,160,27,gImage_ic21);
lcd_show_image(0,90,120,80,gImage_at);
让我们来欣赏一下,演示的效果。
|
感谢分享,MARK一下,学习了
雅特力开发板驱动Arduino接口的LCD屏幕,作者实现效果较好,可尝试用硬件外设代替IO模拟提高刷新率。