Nokia 3310/5110 液晶驱动 汉字和位图点阵生成软件 开放源码
开发环境:WinAVR-20081205相关电路:
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_441260.gif
(原文件名:lcdcircuit.gif)
驱动和演示源码:
/*
*main.c : Demo prog for Nokia3310/5110 LCD driver.
*lcd.h : Driver for Nokia3310/5110 LCD.
*lcd.c : Driver for Nokia3310/5110 LCD.
*Copyright (C) 2005-2009 Zhao Huabing
*www.ursastudio.com.cn
* History: 2005-11-20 Zhao Huabing created
* 2009-03-12 Zhao Huabing modified
*
*This program is free software: you can redistribute it and/or modify
*it under the terms of the GNU General Public License as published by
*the Free Software Foundation, either version 3 of the License, or
*(at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program.If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <avr/io.h>
#include "lcd.h"
#include "bmpix.h"
int main(void)
{
LcdInit();//液晶初始化
LcdDrawBitmap(0, 0, (uint8_t *)logo, 80, 6);//画一个接近全屏的位图
LcdPutString(0, 0, "Ursa Studio");//在位图的左上方覆盖英文字符
LcdPutString(0, 4, "天衡工作室");//在位图的左下方覆盖中文字符
}
#ifndef _LCD_H
#define _LCD_H
/*液晶分辨率定义*/
#define LCD_WIDTH 84
#define LCD_HEIGHT 48
#define LCD_ROW (LCD_HEIGHT/8)
#define LCD_COL LCD_WIDTH
/*液晶控制器端口定义*/
#define LCD_DDR DDRB
#define LCD_PORT PORTB
/*液晶控制器引脚定义*/
#define LCD_SCLK PB7
#define LCD_SDIN PB5
#define LCD_DC PB4
#define LCD_SCE PB1 //低电平使能
#define LCD_RES PB0 //低电平使能
/*参数宏*/
#define COMMAND 0
#define DATA 1
#define POWERDOWN 1
#define ACTIVE 0
#define V_ADDR 1
#define H_ADDR 0
#define EXT_INS 1
#define BAS_INS 0
#define DISPLAY_BLANK 0b000
#define DISPLAY_ALL 0b001
#define NORMAL_MODE 0b100
#define INVERSE_MODE 0b101
// 类型 、操作宏定义
typedef uint8_t bool;
#define true 1
#define false 0
#define bit_get(sfr, bit) ((sfr>>(bit)) & 0x01)
#define bit_set(sfr, bit, val) ((val) ? (sfr |= _BV(bit)) : (sfr &= ~_BV(bit)))
/* 函数声明 */
void LcdInit(void);
void LcdClsScr(void);
void LcdDrawBitmap(uint8_t x, uint8_t y, uint8_t *pBmp, uint8_t row, uint8_t col);
void LcdPutString(uint8_t x, uint8_t y, const char *str);
#endif
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "spi.h"
#include "enpix.h"
#include "cnpix.h"
#include "lcd.h"
// 产生复位脉冲
static void LcdReset(void)
{
bit_set(LCD_PORT, LCD_RES, false);
_delay_us(1);
bit_set(LCD_PORT, LCD_RES, true);
_delay_us(10);
}
// 使能信号传输
// true : 使能 false : 禁止
static void LcdEnable(bool Enable)
{
bit_set(LCD_PORT, LCD_SCE, !Enable);
}
// 发送数据或指令
// DC : 数据或指令
// info : 发送的信息
static void LcdWriteDC(bool DC, uint8_t info)
{
LcdEnable(true);
bit_set(LCD_PORT, LCD_DC, DC);
SpiSendByte(info);
LcdEnable(false);
}
// 发送数据
// Data : 发送的数据
static void LcdWriteData(uint8_t data)
{
LcdWriteDC(DATA, data);
}
// 发送命令
// cmd : 发送的命令
static void LcdWriteCommand(uint8_t cmd)
{
LcdWriteDC(COMMAND, cmd);
}
/*
// 空操作
static void LcdNOP(void)
{
LcdWriteCommand(0);
}
*/
// 功能设置
// Power : 活动或掉电(ACTIVE or POWERDOWN)
// Addr : 水平或垂直寻址(H_ADDR or V_ADDR)
// InsSet : 基本或扩展指令集(BAS_INS or EXT_INS)
static void LcdFunctionSet(bool Power, bool Addr, bool InsSet)
{
LcdWriteCommand(_BV(5) | (Power<<2) | (Addr<<1) | InsSet);
}
/*基本指令集*/
// 显示控制
// DE : DISPLAY_BLANK(显示空白);DISPLAY_ALL(显示全部);
// NORMAL_MODE(普通模式);INVERSE_MODE(反转模式).
static void LcdDispalyControl(uint8_t DE)
{
if(DE != DISPLAY_BLANK && DE != DISPLAY_ALL
&& DE != NORMAL_MODE && DE != INVERSE_MODE)
return;
LcdWriteCommand(_BV(3) | DE);
}
// 设置Y地址
// Addr : 显存Y地址 0~5
static void LcdSetYAddress(uint8_t Addr)
{
if(Addr > 5)
return;
LcdWriteCommand(_BV(6) | Addr);
}
// 设置X地址
// Addr : 显存X地址 0~83
static void LcdSetXAddress(uint8_t addr)
{
if(addr > 83)
return;
LcdWriteCommand(_BV(7) | addr);
}
/*扩展指令集*/
// 设置温度系数
// TC : 温度系数 0~3
static void LcdTempCtrl(uint8_t TC)
{
if(TC > 0x03)
return;
LcdWriteCommand(_BV(2) | TC);
}
// 偏置系统
// BS : 偏置系统 0~7
static void LcdBiasSystem(uint8_t BS)
{
if(BS > 0x07)
return;
LcdWriteCommand(_BV(4) | BS);
}
// 设置操作电压
// Vop : 操作电压 0~0x7f
static void LcdSetVop(uint8_t Vop)
{
if(Vop > 0x7f)
return;
LcdWriteCommand(_BV(7) | Vop);
}
// 设置位置
// x : 显存X地址 0~83
// y : 显存Y地址 0~5
static void LcdSetLocation(uint8_t x, uint8_t y)
{
LcdSetYAddress(y) , LcdSetXAddress(x);
}
//清除屏幕
void LcdClsScr(void)
{
LcdSetLocation(0, 0);
for (uint16_t i=0; i<(LCD_ROW*LCD_COL); i++)
LcdWriteData(0);
}
// 初始化
void LcdInit(void)
{
//输出引脚初始化
LCD_DDR |= _BV(LCD_RES) | _BV(LCD_DC) | _BV(LCD_SCE);
SpiInit();//SPI初始化
LcdReset();//液晶复位
LcdFunctionSet(ACTIVE, H_ADDR, EXT_INS); //扩展指令集
LcdBiasSystem(0x03); //推荐混合率 1:48
LcdSetVop(0x32); //V(6.06) = 3.06 + 0.06*Vop
LcdTempCtrl(0x00); //温度系数 0~3
LcdFunctionSet(ACTIVE, H_ADDR, BAS_INS); //基本指令集
LcdDispalyControl(NORMAL_MODE); //普通模式显示
LcdClsScr();
}
// 绘画位图
// x : x位置
// y : y位置
// pBmp : 位图
// row : 位图行数
// col : 位图列数
void LcdDrawBitmap(uint8_t x, uint8_t y, uint8_t *pBmp, uint8_t col, uint8_t row)
{
if((col > 84) || (row > 6))
return;
for (uint8_t i=0; i<row; i++)
{
LcdSetLocation(x, y);
for(uint8_t j=0; j<col; j++)
LcdWriteData(pgm_read_byte(pBmp+i*col+j));
y++;
}
}
// 清除位图
// x : x位置
// y : y位置
// row : 位图行数
// col : 位图列数
void LcdEraseBitmap(uint8_t x, uint8_t y, uint8_t col, uint8_t row)
{
if((col > 84) || (row > 6))
return;
for (uint8_t i=0; i<row; i++)
{
LcdSetLocation(x, y);
for(uint8_t j=0; j<col; j++)
LcdWriteData(0);
y++;
}
}
// 输出英文字符
// x : x位置
// y : y位置
// c : 英文字符
static void LcdPutEnChar(uint8_t x, uint8_t y, uint8_t c)
{
if((c < 32) || (c >= (32+NUMBER_OF_CHARACTER)))
return;
LcdSetLocation(x, y);
for (uint8_t n=0; n<LCD_ROW; n++)
LcdWriteData(pgm_read_byte((uint8_t *)EnPix+(c-32)*LCD_ROW+n));
}
// 输出汉语字符
// x : x位置
// y : y位置
// c : 汉语字符
static void LcdPutCnChar(uint8_t x, uint8_t y, uint16_t c)
{
uint8_t k;
for(k=0; k<sizeof(CnPix)/34; k++)
if(pgm_read_word((uint16_t *)(CnPix+k*34)) == c)
break;
if(k == sizeof(CnPix)/34)
return;
for(uint8_t i=0; i<2; i++)
{
LcdSetLocation(x, y++);
for(uint8_t j=0; j<16; j++)
LcdWriteData(pgm_read_byte((uint8_t *)(CnPix+k*34+2+16*i+j)));
}
}
// 输出字符串
// x : x位置
// y : y位置
// str : 字符串
void LcdPutString(uint8_t x, uint8_t y, const char *str)
{
uint8_t *p = (uint8_t *)str;
while(*p != 0)
{
if(*p < 128)
{
LcdPutEnChar(x, y, *p);
x += 6;
p++;
}
else
{
LcdPutCnChar(x, y, *(uint16_t *)p);
x += 16;
p += 2;
}
}
}
显示效果:
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_441164.JPG
(原文件名:lcd.JPG)
固件源码下载:
ourdev_441085.zip(文件大小:13K) (原文件名:10-lcd.zip)
汉字点阵生成软件CnPix
说明:
CnPix原为天衡工作室USAVRDKM16开发套件液晶专用汉字点阵生成软件,作为通用软件还需有所修改。
本软件使用QT开发,可跨平台编译使用,支持Windows、Linux/X11和Mac OS X操作系统。
使用方法:
运行软件在编辑栏中输入或粘贴工程需要的所有汉字,回车即可在当前文件夹下产生cnpix.h文件,复制到工程目录即可使用。
预览:
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_441090.png
(原文件名:CnPix.png)
CnPix源码+Windows版下载:
ourdev_441086.zip(文件大小:5.32M) (原文件名:CnPix.zip)
位图点阵生成软件BmPix
说明:
BmPix原为天衡工作室USAVRDKM16开发套件液晶专用位图点阵生成软件,作为通用软件还需有所修改。
本软件使用QT开发,可跨平台编译使用,支持Windows、Linux/X11和Mac OS X操作系统。
本软件目前仅支持单色位图,尺寸不超过84x48像素,高度为8的倍数,如果不满足以上条件,可以先使用画图等程序进行修改转换。
使用方法:
运行软件,添加位图文件,开始转换,可在位图文件同样位置产生同名后缀为h的文件,复制到工程目录即可使用,必要的话可以将得到的文件合并。
预览:
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_441091.png
(原文件名:BmPix.png)
BmPix源码+Windows版下载:
ourdev_441087.zip(文件大小:5.33M) (原文件名:BmPix.zip)
---------------------------------------------------------------------------
版权信息:
以上软件开放源码,使用GPL协议发布。
Copyright (C) 2009 Zhao Huabing
www.ursastudio.com.cn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------------
作者:赵华兵
组织:天衡工作室
网址:www.ursastudio.com.cn
邮箱:ursastudio@gmail.com 这个不错,正好有块5110的LCD闲置,改天试试看。 谢谢,学习了 请教楼主QT相对与BCB有什么优势吗,谢谢 谢谢楼主 谢谢.
在坛子里找5110位图的生成软件.
喊的我嗓子都哑了,终于被你"生"出来了.
再次表示感谢. 试用了一下.
提一点意见:
"高度为8的倍数"这个是不是改一下?只要不超过屏高就可以了吧.限制高度为8的倍数,这似乎.. 回复【3楼】 lionliu
请教楼主QT相对与BCB有什么优势吗,谢谢
-----------------------------------------------------
-- Qt是一个跨平台的C++图形用户界面应用程序框架,而Borland C++ Builder是一款可视化集成开发工具,所以它们比较不太对等,与QT对等的应该是VCL(Visual Component Library),它是Delphi,C++Builder等编程语言的基本类库。
-- QT跨平台,支持Windows、Linux/X11、Mac OS X、Windows CE、Embedded Linux等操作系统;VCL封装大量Win32 API,这是无法移植到其它不兼容平台的。目前QT所在的公式被诺基亚收购,至此诺基亚、摩托罗拉等世界顶级手机厂商的高端手机都已经或者将要使用QT作为图形界面的开发平台。
-- 由于QT只是一个图形用户界面应用程序框架,并且是跨平台的,所以对底层硬件和某些操作系统特有的功能的支持有限,需要特别使用本地API进行或者其他封装类库进行访问,在这一点上恐怕没有VCL方便。
-- 它们的应用程序结构不同,至于谁更简洁便利,我没用过C++ Builder,因此不便多做评价。
暂时这些,请各位达人发表意见。 回复【6楼】 wisebaby 明君
"高度为8的倍数"这个是不是改一下?只要不超过屏高就可以了吧.限制高度为8的倍数,这似乎..
-----------------------------------------------------
之所以将高度限制为8的倍数,这是和液晶驱动器硬件的特征相关。下图是液晶内部显存的结构,注意它的纵向是以8个像素(一个字节)为操作单位的,再加上这个显存是个只写的,这就给图像的操作带来了相应的限制。
http://cache.amobbs.com/bbs_upload782111/files_14/ourdev_441161.png
(原文件名:ramformat.png)
由此可知,如果图像的高度或者起始的纵坐标不是8的倍数的话,使用当前的驱动程序很难保证在完整显示图像的情况下而不覆盖超出图像的区域。
当然也有其他的方法,比如使用液晶显存在内存中的映射,这种方法可以把显存“变成”可以读写的,也就解决了图像高度或者起始的纵坐标8的倍数的限制,可以在任意位置显示任意尺寸的图片,但是这种方法的缺点是需要消耗至少和显存大小相等的内存空间,Nokia3310/5110液晶的显存是84x6=504字节,对于只有1K内存的Mega16来说消耗还是很大的,而且每次操作可能更新整个显存或者使用更复杂的算法,所以除非在更大内存更快速度的系统(例如Nokia手机)使用这种方法或者特殊的应用,一般不推荐这种做法,那么简单的做法就是限制图像的高度或者起始纵坐标为8的倍数,这在一般情况下也够用了。 程序写的好,也容易读!赞一个! 请问楼主有没有5110的引脚信息??小弟谢谢了 实在太有用了,刚好派上用场!谢谢了 看着似乎很好用,先顶一下,谢谢楼主!!!我下下来试试。 顶下! mark mark 好! 我刚弄好5110+51,很好! 感谢 不错 下来试试看
顶下先 mark MARK 楼主很强悍,支持^_^ 学习,正在写 顶 支持下 不错,学习 mark 标记 mark~~~ 回复【楼主位】ursastudio
-----------------------------------------------------------------------
好东西,感谢分享 很棒哈! mark mark makr 谢谢分享,学习下…… 不错的东西!谢谢分享 up ding 楼主强悍,mark! mark mark mark 学习了~ 好东西…… 拿去用,谢谢了。。 mark mark 感谢楼主,还想问一下如何实现液晶显示的转置,也就是说把5110旋转90度后再实现正面显示?谢谢~~~ 学习了 好 dddddddddd顶
顶!
页:
[1]