这是用msp430来控制基于NT7532控制器的12864液晶的范例,用的是北京青云科技的LCM12864H液晶屏,是学校实验用的程序。 我感觉这种程序写的很牛叉,即使看不懂也会调用,一个一个模块太清楚了,不仅他写的清楚,看的人也舒服。现在贴在下面,时刻欣赏:
下面头文件是lcd12864.h
/**************************************************
**************************************************/
#ifndef __LCD12864_H
#define __LCD12864_H
#include "main.h"
#define lcd_Cols 16
#define lcd_Rows 4
#define ROW1 0
#define ROW2 1*lcd_Cols
#define ROW3 2*lcd_Cols
#define ROW4 3*lcd_Cols
extern BYTE lcd_Index;
//extern BYTE lcd_Row;
//extern BYTE lcd_Col;
#define ToLineEnd (lcd_Cols-lcd_Index%lcd_Cols)
void delay_us(BYTE n);
void delay_ms(BYTE n);
void LcdIni(void);
void lcd_clear(void);
void LcdPutChar8(BYTE * ch8);
void LcdPutChar16(BYTE * ch16);
void LcdString8(BYTE *First,BYTE len);
void LcdString16(BYTE *First,BYTE len);
void LcdNumbers(WORD num,BYTE len,BYTE dot);
#endif /* __LCD12864_H */
//下面文件是lcd12864.c的模块
/*
*;This source file is for 12864H graphic liquid crystal module ***
*;SDA=P3.1,SCK=P3.3,[/RES=...]
*;/CS1=P3.0,D/C=P3.2
*/
#include <msp430x14x.h>
#include "hz16.h"
#include "lcd12864.h" //因为lcd12864.h里面已经包含了main.h,所以不用再包含main.h
#define SCK_DIR_OUT P3DIR |= BIT3 /* 串行输入时脉冲信号 */
#define DnC_DIR_OUT P3DIR |= BIT2 /* D/C为高,输入为数据;D/C为低,输入为指令 */
#define SDA_DIR_OUT P3DIR |= BIT1 /* 串行输入时数据信号 */
#define nCS_DIR_OUT P3DIR |= BIT0 /* 片选信号,低有效 */
// #define DATADIR P1DIR
// #define DATAOUT P1OUT
// #define DATAIN P1IN
// #define DATA_DIROUT DATADIR = 0xff /* 8位数据口输出 */
// #define DATA_DIRIN DATADIR = 0x00 /* 8位数据口输入 */
#define bis_SCK P3OUT |= BIT3
#define bis_DnC P3OUT |= BIT2
#define bis_SDA P3OUT |= BIT1
#define bis_nCS P3OUT |= BIT0
#define bic_SCK P3OUT &= ~BIT3
#define bic_DnC P3OUT &= ~BIT2
#define bic_SDA P3OUT &= ~BIT1
#define bic_nCS P3OUT &= ~BIT0
#define lcd_CLK_Delay {}
// 光标位置
BYTE lcd_Index;
//BYTE lcd_Row;
//BYTE lcd_Col;
void delay_us(unsigned char n)
{
unsigned char i;
i=n;
while(i!=0)
{ //3CLK
_NOP();
_NOP();
_NOP();
_NOP();
i--; //1CLK
}
}
void delay_ms(unsigned char n)
{
unsigned char i;
i=n;
while(i!=0)
{ //3CLK
delay_us(250);
delay_us(250);
delay_us(250);
delay_us(250);
i--; //1CLK
}
}
/* 发字节到LCD MSB*/
void lcd_SendByte(uchar x)
{
uchar i,n=0x80;
for(i=0;i<8;i++)
{
if (x&n) bis_SDA;
else bic_SDA;
n=n>>1;
lcd_CLK_Delay;
bis_SCK;
lcd_CLK_Delay;
bic_SCK;
lcd_CLK_Delay;
bis_SCK;
}
}
/* 发字节到LCD LSB 为了兼容lcd12232的字库*/
void lcd_SendByteLSB(uchar x)
{
uchar i,n=0x01;
for(i=0;i<8;i++)
{
if (x&n) bis_SDA;
else bic_SDA;
n=n<<1;
lcd_CLK_Delay;
bis_SCK;
lcd_CLK_Delay;
bic_SCK;
lcd_CLK_Delay;
bis_SCK;
}
}
/* 发命令x到主窗口*/
void lcd_MC(uchar x)
{
bis_SCK;
bic_nCS;
bic_DnC;
lcd_SendByte(x);
bis_nCS;
}
/* 写数据x到主窗口*/
void lcd_MD(uchar x)
{
bis_SCK;
bic_nCS;
bis_DnC;
lcd_SendByteLSB(x);
bis_nCS;
}
/* 清屏 */
void lcd_clear(void)
{
uchar i;
uchar page;
for (page=0;page<8;page++)
{
lcd_MC(0xB0|page);//lcd_SC(0xB0|page); // 设置显示页面
// 这个屏COL是从1~128不是0~127 COL 从1开始
lcd_MC(0x10);//lcd_SC(0&0x1F); // 设置列地址高位
lcd_MC(0x01);//lcd_SC(0&0x0F); // 设置列地址低位
for (i=0;i<128;i++)
{
lcd_MD(0x00);//lcd_SD(0x00);
}
}
}
/* 画一个图,横座标是X,layer表示0,1,2,3层,width是图形的宽,高都是16,bmp是图形
指针 */
/* 使用zimo21软件,采用纵向取模,字节倒序,得到bmp数据 */
void lcd_DrawBmp(uchar x0,uchar layer,uchar width,uchar *bmp)
{
uchar x,i=0;
// address表示显存的物理地址
uchar page=0;
// page 表示3,2,1,0,7,6,5,4页
switch (layer)
{
case 0: page=3; break;
case 1: page=1; break;
case 2: page=7; break;
case 3: page=5; break;
default: return;
}
// 这个屏COL是从1~128不是0~127
for (x=x0+1;x<x0+width+1;x++)
{ // 一次显示两页
lcd_MC(0xB0|page);
lcd_MC(((x>>4)&0x0f)|0x10); // 设置列地址高位
lcd_MC(x&0x0F); // 设置列地址低位
lcd_MD(bmp[i]); // 画上层
lcd_MC(0xB0|(page-1));
lcd_MC(((x>>4)&0x0f)|0x10); // 设置列地址高位
lcd_MC(x&0x0F); // 设置列地址低位
lcd_MD(bmp[i+width]); // 画下层
i++;
}
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdPutChar8(BYTE * ch8)
函数说明:显示半角字符,8位宽,汉字占两个8位
从lcd_Index开始显示
BYTE * ch8 : 点阵数组指针
--------------------------------------------------------------------------------
-*/
void LcdPutChar8(BYTE * ch8)
{
BYTE x;
uchar layer;
layer=(lcd_Index/16)%4;
x=lcd_Index%16;
lcd_DrawBmp(x*8,layer,8,ch8);
lcd_Index=(layer*lcd_Cols+x+1)%64; // 更新光标指针
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdPutChar16(BYTE * ch16)
函数说明:显示全角字符,汉字占两个8位
从lcd_Index开始显示
BYTE * ch16 : 点阵数组指针
--------------------------------------------------------------------------------
-*/
void LcdPutChar16(BYTE * ch16)
{
BYTE x;
uchar layer;
layer=lcd_Index/16;
x=lcd_Index%16;
if (x==15)
{
x=0;
layer++;
}
layer=layer%4;
lcd_DrawBmp(x*8,layer,16,ch16);
lcd_Index=(layer*lcd_Cols+x+2)%64; // 更新光标指针
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdString8(BYTE *First,BYTE len){
函数说明:显示半角字符串,8位宽,汉字占两个8位
从lcd_Index开始显示
First : 字符串点阵数组的首指针
len : 字串长度
--------------------------------------------------------------------------------
-*/
void LcdString8(BYTE *First,BYTE len){
BYTE i;
for(i=0;i<len;i++){
LcdPutChar8((BYTE *)(First+i*16)); // 8位字每个字符的点阵为16Bytes
}
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdString16(BYTE *First,BYTE len){
函数说明:显示汉字全角字符串,16位宽
从lcd_Index开始显示
First : 字符串点阵数组的指针
len : 字串长度
--------------------------------------------------------------------------------
-*/
void LcdString16(BYTE *First,BYTE len)
{
BYTE i;
for(i=0;i<len;i++)
{
LcdPutChar16((BYTE *)(First+i*32)); // 16位字每个字符的点阵为 32 Bytes
}
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdNumbers(WORD num,BYTE len,BYTE dot){
函数说明:显示半角数字字符串,8位宽,汉字占两个8位
从lcd_Index开始显示
num : 要显示的数字 0~65535
len : 格式化数字的长度
dot : 小数点位数, 0:没有小数点
--------------------------------------------------------------------------------
-*/
void LcdNumbers(WORD num,BYTE len,BYTE dot){
BYTE n,temp,start;
int i;
WORD numTemp;
numTemp=num;
n=len;
start=lcd_Index;
if (dot!=0) n++;
for(i=n-1;i>=0;i--){
lcd_Index=start+i;
if ( ((n-1-dot)==i) && (dot!=0) )
{
LcdPutChar8((BYTE *)CHAR_DOT);
continue;
}
temp=numTemp%10;
numTemp/=10;
LcdPutChar8((BYTE *)CHAR_Numbers[temp]); // 8位字每个字符的点阵为16Bytes
}
lcd_Index=start+n;
}
/*------------------------------------------------------------------------------
--
调用方式:void LcdIni(void)
函数说明:12232点阵液晶初始化,开机后仅调用一次。
--------------------------------------------------------------------------------
-*/
void LcdIni(void){
SCK_DIR_OUT;
DnC_DIR_OUT;
SDA_DIR_OUT;
nCS_DIR_OUT;
//bis_nCS;
delay_ms(250);
delay_ms(250);
lcd_MC(0xE2);//lcd_SC(0XE2); //;built-in OS(24)
lcd_MC(0x2F);//lcd_SC(0X2F); //;power control register(16)
lcd_MC(0x81);//lcd_SC(0X81); //;electronic control mode set(18)
lcd_MC(0x31);//lcd_SC(0X31); //;electronic control register set(18)
lcd_MC(0xA2);//lcd_SC(0XA2); //;bias=1/9(11)
lcd_MC(0xA0);//lcd_SC(0XA0); //;ADC,clo0 maps seg0(8)
lcd_MC(0xC0);//lcd_SC(0XC0); //;remapped mode.com0-->comn(15)
lcd_MC(0x40);//lcd_SC(0X40); //;set display start line=0(2)
lcd_clear();// 清屏
lcd_MC(0xAF);//lcd_SC(0XAF); //;display on(1)
delay_ms(250);
delay_ms(250);
// LcdString8(lcd_Index,(BYTE *)CHAR_Numbers[0],10);// LOGO
delay_ms(250);
delay_ms(250);
}
//下面的头文件是上面程序中涉及到的mian.h
/**************************************************
**************************************************/
#ifndef __MAIN_H
#define __MAIN_H
#include "msp430x14x.h"
#include "HardDelay.h"
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
#define DDWORD unsigned long long
#define uchar unsigned char
#define bit BYTE
//P1口按键定义
#define S3 BIT0
#define S4 BIT1
#define S5 BIT2
#define S6 BIT3
#define S7 BIT4
/******************************************************************
外挂存储器 SS25010,SPI方式占用口线4根:P5.0~P5.3
*******************************************************************/
#define CE BIT0 //P5口
#define SI BIT1
#define SO BIT2
#define SCK BIT3
//灯口线定义
#define LEDR BIT6
#define LEDG BIT5
#endif /* __MAIN_H */
PS: 本文结束了,我也要像这样写程序