| |
汗,发了一半不小心提交了,继续 (原文件名:图片4.png) 只要我们清楚了它的GDRAM和屏幕上像素点的映射(对应)关系,点亮对应的像素点就容易多了。要点亮某一个像素点,就是将这个像素点在GDRAM中对应的位置1,这个相信没人会不知道吧? 我们先讨论一下思路,再一步步写代码。我觉得,思路要比代码重要的多,只要你的思路通了,正确了,那么写出代码肯定会很容易。 首先,给你x,y的坐标,要你点亮一个点,要怎么做呢?从上面的图我们知道,它是分为两个半屏的,首先,我们要确定这个点是在上半屏还是下半屏,然后确定它是在那一行(纵坐标Y),再确定它是在哪一个字节的哪一个位(也就是确定它在那一列,即横坐标X)。这些都确定后我们就定位到某一个具体的位上了,只就将这个位置1,就OK了。 下面我们边写代码边讨论。 因为这里仅仅是讨论如何在12864上打点的,而不是给12864写一个驱动,所以对于基本的数据读写函数,我们不做讨论,这里假设已经有了如下基本函数: void lcd_write_cmd(unsigned char); //lcd 命令写 void lcd_write_data(unsigned char); //lcd 数据写 unsigend char lcd_read_data(void); //lcd 数据读 好了,就这些了。 为了方便,我们定义如下宏: #define BASIC_SET 0x00 //基本指令集,后面的数字查数据手册,下同。 #define EXTEND_SET 0x00 //扩展指令集 #define DRAW_ON 0x00 //绘图显示开 #define DRAW_OFF 0x00 //绘图显示关 我们现在开始写点亮某一个点的函数: void lcd_set_dot(unsigned char x, unsigned char y) { unsigned char x_byet, x_bit; //在横坐标的哪一个字节,哪一个位 unsigned char y_byte, y_bit; x_byte = x / 16; //算出它在哪一个字节(地址) //注意一个地址是16位的 x_bit = x % 16; //算出它在哪一个位 y_byte = y /32; //y是没在哪个字节这个说法 //这里只是确定它在上半屏还是下半屏 //0:上半屏 1:下半屏 y_bit = y % 32; //y_bit确定它是在第几行 lcd_write_cmd(EXTEND_SET); //扩展指令集 lcd_write_cmd(DRAW_OFF); //绘图显示关闭 lcd_write_cmd(0x80 + y_bit); //先写垂直地址 //具体参照数据手册 lcd_write_cmd(0x80 + x_byte + 8 * y_byte); //水平坐标 //下半屏的水平坐标起始地址为0x88 //(+8*y_byte)就是用来确定在上半屏还是下半屏 if (x_bit < 8) //如果x_bit位数小于8 { lcd_write_data(0x01 << (7 - x_bit)); //写高字节。因为坐标是从左向右的 //而GDRAM高位在左,底位在右 lcd_write_data(0x00); //低字节全部填0 } else { lcd_write_data(0x00); //高字节全部填0 lcd_write_data(0x01 << (15 - x_bit)); } lcd_write_cmd(DRAW_ON); //打开绘图显示 lcd_write_cmd(BASIC_SET); //回到基本指令集,毕竟ST7920是以字符为主的 return ; } 基本画点函数算是完成了,但是我们如果使用这个函数,就会发现问题。你且用它沿横坐标画几个连续的点试试,肯定不是你想要的结果。 出现问题的原因是因为我们画点时对其余的位全部填0处理了,造成对原来的信息的破坏。所以我们要读出要写的那个地址原来的数据,再进行加工,写回去就可以解决问题了。 改进后的代码: void lcd_set_dot(unsigned char x, unsigned char y) { unsigned char x_byet, x_bit; //在横坐标的哪一个字节,哪一个位 unsigned char y_byte, y_bit; unsigned char tmph, tmpl; //定义两个临时变量,用于存放读出来的数据 x &= 0x7F; y &= 0x3F; x_byte = x / 16; //算出它在哪一个字节(地址) //注意一个地址是16位的 x_bit = x&0x0F; //算出它在哪一个位 y_byte = y /32; //y是没在哪个字节这个说法 //这里只是确定它在上半屏还是下半屏 //0:上半屏 1:下半屏 y_bit = y&0x3F; //y_bit确定它是在第几行 lcd_write_cmd(EXTEND_SET); //扩展指令集 lcd_write_cmd(DRAW_OFF); //绘图显示关闭 lcd_write_cmd(0x80 + y_bit); //先写垂直地址(最高位必须为1) //具体参照数据手册 lcd_write_cmd(0x80 + x_byte + 8 * y_byte); //水平坐标 //下半屏的水平坐标起始地址为0x88 //(+8*y_byte)就是用来确定 //在上半屏还是下半屏 lcd_read_data(); //先空读一次 tmph = lcd_read_data(); //读高位 tmpl = lcd_read_data(); lcd_write_cmd(0x80 + y_bit); //读操作会改变AC,所以重新设置一次 lcd_write_cmd(0x80 + x_byte + 8 * y_byte); if (x_bit < 8) //如果x_bit位数小于8 { lcd_write_data(tmph | (0x01 << (7 - x_bit))); //写高字节。因为坐标是从左向右的 //而GDRAM高位在左,底位在右 lcd_write_data(tmpl); //原数据送回 } else { lcd_write_data(tmph); //原数据送回 lcd_write_data(tmpl | (0x01 << (15 - x_bit))); } lcd_write_cmd(DRAW_ON); //打开绘图显示 lcd_write_cmd(BASIC_SET); //回到基本指令集,毕竟ST7920是以字符为主的 return ; } 画点函数到此就完成了,剩下的事情就是对函数的优化了。例如对入口参数的检查,对乘除法的优化等等。 |
欢迎光临 因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/) | Powered by Discuz! X3.4 |