#include "msp430x26x.h"
#define uchar unsigned char
#define uint unsigned int
#define iDat 1 //数据标志
#define iCmd 0 //指令标志
#define LCDb_RS 0x20 //定义四个控制引脚
#define LCDb_RW 0x40
#define LCDb_E 0x80
#define LCDb_RST 0x04
#define LCDb_L1 0x80 //第一行的地址
#define LCDb_L2 0x90 //第二行的地址
#define LCDb_L3 0x88 //第三行的地址
#define LCDb_L4 0x98 //第四行的地址
#define LCDb_SET_RS P1OUT|=LCDb_RS //四个控制管脚的控制 *** 作
#define LCDb_SET_RW P1OUT|=LCDb_RW
#define LCDb_SET_E P1OUT|=LCDb_E
#define LCDb_SET_RST P8OUT|=LCDb_RST
#define LCDb_CLR_RS P1OUT&=~LCDb_RS
#define LCDb_CLR_RW P1OUT&=~LCDb_RW
#define LCDb_CLR_E P1OUT&=~LCDb_E
#define LCDb_CLR_RST P8OUT&=~LCDb_RST
#define LCDb_DO P4OUT //输出数据总线端口定义
#define LCDb_FUNCTION 0x38 // 液晶模式为8位,2行,5*8字符
#define LCDb_BASCMD 0x30 // 基本指令集
#define LCDb_CLS 0x01 // 清屏
#define LCDb_HOME 0x02 // 地址返回原点,不改变DDRAM内容
#define LCDb_ENTRY 0x06 // 设定输入模式,光标加,屏幕不移动
#define LCDb_C2L 0x10 // 光标左移
#define LCDb_C2R 0x14 // 光标右移
#define LCDb_D2L 0x18 // 屏幕左移
#define LCDb_D2R 0x1C // 屏幕又移
#define LCDb_ON 0x0C // 打开显示
#define LCDb_OFF 0x08 // 关闭显示
unsigned char RXData
unsigned char Seg_Data[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} //数码管编码
unsigned char Result[5] //整数转化成字符串,给LCD显示
void Delayms(uint MS)
{
uint i,j
for( i=0i<MSi++)
for(j=0j<1141j++)
}
void Delayus(uint US)
{
uint i
US=US*5/4
for( i=0i<USi++)
}
void LCD12864_portini()
{
P1DIR=0xFF
P4DIR=0xFF
P5DIR=0xFF
P8DIR=0xFF
P8OUT |=LCDb_RST
//P1OUT=0xFF
}
/*函数名称: LCD12864_sendbyte
功能: 向12864液晶写入一个字节数据或者指令
*/
void LCD12864_sendbyte(uchar DatCmd, uchar dByte)
{
if (DatCmd == iCmd) //指令 *** 作
LCDb_CLR_RS
else
LCDb_SET_RS
LCDb_CLR_RW //写 *** 作
LCDb_SET_E
LCDb_DO = dByte //写入数据
//Delayus(500)
Delayms(1)
LCDb_CLR_E
}
/*函数名称: LCD12864_sendstr
功能: 向12864液晶写入一个字符串
参数: ptString--字符串指针
返回值 : 无
*/
void LCD12864_sendstr(uchar *ptString)
{
while((*ptString)!='\0') //字符串未结束一直写
{
LCD12864_sendbyte(iDat, *ptString++)
}
}
/*函数名称: LCD12864_clear
功能: 12864液晶清屏
参数: 无
返回值 : 无
*/
void LCD12864_clear(void)
{
LCD12864_sendbyte(iCmd,LCDb_CLS)
Delayms(2)// 清屏指令写入后,2ms 的延时是很必要的!!!
}
/*
函数名称: LCD12864_gotoXY
功能: 移动到指定位置
参数: Row--指定的行
Col--指定的列
返回值 : 无
*/
void LCD12864_gotoXY(uchar Row, uchar Col)
{
switch (Row) //选择行
{
case 2:
LCD12864_sendbyte(iCmd, LCDb_L2 + Col)break //写入第2行的指定列
case 3:
LCD12864_sendbyte(iCmd, LCDb_L3 + Col)break //写入第3行的指定列
case 4:
LCD12864_sendbyte(iCmd, LCDb_L4 + Col)break //写入第4行的指定列
default:
LCD12864_sendbyte(iCmd, LCDb_L1 + Col)break //写入第1行的指定列
}
}
/*
函数名称: LCD12864_initial
功能: 12864液晶初始化
*/
void LCD12864_initial(void)
{
Delayms(100) // 等待内部复位
LCD12864_portini() //端口初始化
LCD12864_sendbyte(iCmd, LCDb_FUNCTION) //功能、模式设定
LCD12864_sendbyte(iCmd, LCDb_ON) //打开显示
LCD12864_clear() //清屏
LCD12864_sendbyte(iCmd, LCDb_ENTRY) // 输入模式设定
}
void Int_char(int data)
{
if(data/1000)
{
Result[0]=data/1000+'0'
Result[1]=data/100%10+'0'
Result[2]=data/10%10+'0'
Result[3]=data%10+'0'
Result[4]=0
}
else if(data/100)
{
Result[0]=data/100+'0'
Result[1]=data/10%10+'0'
Result[2]=data%10+'0'
Result[3]=0
}
else if(data/10)
{
Result[0]=data/10%10+'0'
Result[1]=data%10+'0'
Result[2]=0
}
else
{
Result[0]=data%10+'0'
Result[1]=0
}
}
unsigned char Key_Press(void)
{
P7OUT=0xF0
if((P7IN&0x10)&&(P7IN&0x20)&&(P7IN&0x40)&&(P7IN&0x80)) return 0x00
else return 0xFF
}
unsigned char Get_Keycode(void)
{
while(1)
{
P7OUT=0xFE //扫描第一列
if((P7IN&0x10)==0) return 0
else if((P7IN&0x20)==0) return 4
else if((P7IN&0x40)==0) return 8
else if((P7IN&0x80)==0) return 12
P7OUT=0xFD //扫描第二列
if((P7IN&0x10)==0) return 1
else if((P7IN&0x20)==0) return 5
else if((P7IN&0x40)==0) return 9
else if((P7IN&0x80)==0) return 13
P7OUT=0xFB //扫描第三列
if((P7IN&0x10)==0) return 2
else if((P7IN&0x20)==0) return 6
else if((P7IN&0x40)==0) return 10
else if((P7IN&0x80)==0) return 14
P7OUT=0xF7 //扫描第四列
if((P7IN&0x10)==0) return 3
else if((P7IN&0x20)==0) return 7
else if((P7IN&0x40)==0) return 11
else if((P7IN&0x80)==0) return 15
}
}
void Init_compa()
{
CACTL1 = CAON+CAREF_2+CARSEL// Enable Comp, ref = 0.5*Vcc = Vin-
CACTL2 = P2CA0 // Pin to CA0
P1DIR |= 0x01 // P1.0 = o/p direction(CAOUT - LED)
P1SEL |= 0x01 // P1.0 - CAOUT, option select
}
/*
** 函数名称:初始化函数
*/
void Init_IIC(void)
{
P3SEL |= 0x06 // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC// I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST // Use SMCLK, keep SW reset
UCB0BR0 = 12// fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0
UCB0I2CSA = 0x50 // Slave Address is 048h
UCB0CTL1 &= ~UCSWRST// Clear SW reset, resume operation
IE2 |= UCB0RXIE // Enable RX interrupt
_BIS_SR(GIE)
// RXCompare = 0x0 // Used to check incoming data
}
/** 函数名称:字节写函数
*/
void EEPROM_Write(unsigned char high_Address,unsigned char low_Address,unsigned char Word)
{
while (UCB0CTL1 &UCTXSTP) // 确定总线空闲
UCB0CTL1 |= UCTXSTT + UCTR // 发送起始位,确定为发送模式
UCB0TXBUF = high_Address// 发送高位地址
while((IFG2 &UCB0TXIFG)==0) // 判断是否发送完毕
UCB0TXBUF = low_Address // 发送低位地址
while((IFG2 &UCB0TXIFG)==0) // 判断是否发送完毕
UCB0TXBUF = Word// 发送数据
while((IFG2 &UCB0TXIFG)==0) // 判断是否发送完毕
UCB0CTL1 |= UCTXSTP // 发送停止位
while((UCB0CTL1 &UCTXSTP)==1) // 判断停止位是否发送完毕
}
/**
** 函数名称:字节读函数
*/
void EEPROM_readmore()
{
UCB0CTL1 &= ~UCTR // 确定为读
while (UCB0CTL1 &UCTXSTP) // 总线是否空闲
UCB0CTL1 |= UCTXSTT// 发送开始位
}
/*
** 函数名称:字节写函数
**/
void EEPROM_read(unsigned char high_Address,unsigned char low_Address)
{
while (UCB0CTL1 &UCTXSTP) // Ensure stop condition got sent
UCB0CTL1 |= UCTXSTT + UCTR // 发送起始位,确定为写
UCB0TXBUF = high_Address// 发送地址位高位
while((IFG2 &UCB0TXIFG)==0) // 判断是否发送完毕
UCB0TXBUF = low_Address // 发送地址位低位
while((IFG2 &UCB0TXIFG)==0) // 判断是否发送完毕
UCB0CTL1 &= ~UCTR // 确定为接收
while (UCB0CTL1 &UCTXSTP) //
UCB0CTL1 |=UCTXSTT
while((UCB0CTL1 &UCTXSTT)==1)
for(unsigned char i=0x0i<0x2fi++) // 延时确定数据已经被发送出去
UCB0CTL1 |=UCTXSTP + UCTXNACK // 发送停止位和NACK位
}
/*
** 函数名称:接收中断函数
**/
// USCI_B0 Data ISR
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
RXData = UCB0RXBUF // Get RX data
Int_char(RXData)
LCD12864_gotoXY(2,0) //第2行,第1列显示
LCD12864_sendstr(Result)
/*
key_code[0]=RXData%10+'0'
key_code[1]=0
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr(key_code)
*/
// __bic_SR_register_on_exit(CPUOFF) // Exit LPM0
}
void Init_UART()
{
P3OUT &= ~(BIT4+BIT5+BIT6+BIT7)
P3SEL = 0xF0// P3.4,5,6,7 = USCI_A0 TXD/RXD USCI_A1 TXD/RXD
UCA0CTL1 |= UCSSEL_1// CLK = ACLK
UCA0BR0 = 0x03 // 32kHz/9600 = 3.41
UCA0BR1 = 0x00 //
UCA0MCTL = UCBRS1 + UCBRS0 // Modulation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST// **Initialize USCI state machine**
IE2 |= UCA0RXIE // Enable USCI_A0 RX interrupt
UCA1CTL1 |= UCSSEL_1// CLK = ACLK
UCA1BR0 = 0x03 // 32kHz/9600 = 3.41
UCA1BR1 = 0x00 //
UCA1MCTL = UCBRS1 + UCBRS0 // Modulation UCBRSx = 3
UCA1CTL1 &= ~UCSWRST// **Initialize USCI state machine**
UC1IE |= UCA1RXIE // Enable USCI_A0 RX interrupt
_BIS_SR(GIE)//使能中断
}
void Init_ADC()
{
ADC12CTL0 = SHT0_2 + ADC12ON// Set sampling time, turn on ADC12
ADC12CTL1 = SHP // Use sampling timer
ADC12IE = 0x01 // Enable interrupt
ADC12CTL0 |= ENC// Conversion enabled
P6DIR &= 0x01 // P6.0, i/p
P6SEL |= 0x01 // P6.0-ADC option select
_BIS_SR(GIE)//使能中断
}
void Start_ADC()
{
ADC12CTL0 |= ADC12SC // Start convn, software controlled
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2&UCA0TXIFG)) // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF // TX ->RXed character
LCD12864_sendbyte(iDat,UCA0RXBUF)
}
#pragma vector=USCIAB1RX_VECTOR
__interrupt void USCI1RX_ISR(void)
{
while (!(UC1IFG&UCA1TXIFG)) // USCI_A0 TX buffer ready?
UCA1TXBUF = UCA1RXBUF // TX ->RXed character
LCD12864_sendbyte(iDat,UCA0RXBUF)
//UCA1TXBUF = 'z'
}
// ADC12 interrupt service routine
#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR (void)
{
int i=ADC12MEM0
Int_char(i)
LCD12864_gotoXY(2,0) //第1行,第1列显示
LCD12864_sendstr(Result)
/*
key_code[0] =i/1000+'0'
key_code[1] =i/100%10+'0'
key_code[2] =i/10%10+'0'
key_code[3] =i%10+'0'
key_code[4] =0
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr(key_code)
*/
}
void Init_all()
{
LCD12864_initial()//LCD初始化,包含了数码管和LED灯初始化
P7DIR=0x0F //键盘扫描初始化
P7REN=0xF0 //输入上下拉电阻使能,输出上下拉不使能
P7OUT=0xF0//输入上拉
Init_UART()//串口初始化
Init_compa()//比较器初始化
Init_ADC()//ADC初始化
Init_IIC()//IIC初始化
}
void Test_Led()
{
unsigned char i=0
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("1.Test_LED")
for(i<16i++)
{
P8OUT=0xF0|i
Delayms(50)
}
}
void Test_Seg()
{
int i
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("2.Test_SEG")
for(i=0i<500i++)
{
//4,3,2,1
P1OUT&=~0x02
P1OUT|=0x10|0x08|0x04
P5OUT=Seg_Data[9] //清楚数码管显示
Delayms(1)
P1OUT&=~0x04
P1OUT|=0x10|0x08|0x02
P5OUT=Seg_Data[8] //清楚数码管显示
Delayms(1)
P1OUT&=~0x08
P1OUT|=0x10|0x04|0x02
P5OUT=Seg_Data[7] //清楚数码管显示
Delayms(1)
P1OUT&=~0x10
P1OUT|=0x08|0x04|0x02
P5OUT=Seg_Data[6] //清楚数码管显示
Delayms(1)
}
P5OUT=0x00//熄灭所有数码管
}
void Test_Key()
{
unsigned char i=0
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("3.Test_KEY")
LCD12864_gotoXY(2,0) //第2行,第1列显示
LCD12864_sendstr("按键:")
for(i<16i++)
{
Int_char(Get_Keycode())
LCD12864_gotoXY(2,3)
LCD12864_sendstr("")
LCD12864_gotoXY(2,3)
LCD12864_sendstr(Result)
Delayms(100)//防抖
}
}
void Test_Uart()
{
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("4.Test_UART")
LCD12864_gotoXY(2,0) //第2行,第1列显示
}
void Test_Compa()
{
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("5.Test_COMPA")
}
void Test_ADC()
{
int i=0
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("6.Test_ADC")
for(i<200i++)
{
Start_ADC()
Delayms(10)
}
}
void Test_IIC()
{
LCD12864_gotoXY(1,0) //第1行,第1列显示
LCD12864_sendstr("7.Test_IIC")
EEPROM_Write(0x00,0x40,7)// 字节写
Delayms(10)
EEPROM_read(0x00,0x40)
}
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD//关闭看门狗
Init_all()
while(1){
Test_Led() //1.测试LED
LCD12864_gotoXY(2,0) //第1行,第1列显示
LCD12864_sendstr("请按16键!")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
Test_Seg() //2.测试数码管
LCD12864_gotoXY(2,0) //第1行,第1列显示
LCD12864_sendstr("请按16键!")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
Test_Key() //3.测试按键扫描
LCD12864_gotoXY(2,0) //第1行,第1列显示
LCD12864_sendstr("请按16键!")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
LCD12864_gotoXY(3,0) //第3行,第1列显示
LCD12864_sendstr("请按16键!")
Test_Uart() //4.测试串口
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
Test_Compa() //5.测试比较器
LCD12864_gotoXY(2,0) //第2行,第1列显示
LCD12864_sendstr("请按16键!")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
Test_ADC() //6.测试ADC
LCD12864_gotoXY(3,0) //第3行,第1列显示
LCD12864_sendstr("请按16键!")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
Test_IIC() //7.测试IIC
Delayms(100)
LCD12864_gotoXY(3,0) //第3行,第1列显示
LCD12864_sendstr("测试完成")
while(!(Get_Keycode()==15)) //按下最后一键测试下一个例子
LCD12864_clear()
}
}
/*LCD12864显示程序此程序控制LCD12864液晶屏,IC为KS0108或兼容型号
图形文件获取方法:
在字模提取V21软件中 ,导入一幅128*64黑白图像.
* 参数设置:
* 参数设置->其它选项,选择纵向取模,勾上字节倒序,保留逗号,
* 取模方式为C51。
将生成的数组通过keilc等C编译软件,在编译软件中新建一工程,写入源程序如下:
unsigned char code tab[]=
{
//图像数据
}
编译此工程将得到hex文件.在QII中使用lpm_rom宏功能模块中调用此hex文件.
*
*******************************************************************************/
module newlcd(clock,rst_n,rs,rw,en,data,lcd_cs)
// I/O口声明
input clock //系统时钟
input rst_n //复位信号
output[1:0] lcd_cs //
outputrs //1:数据模式;0:指令模式
outputrw //1:读 *** 作;0:写 *** 作
outputen //使能信号,写 *** 作时在下降沿将数据送出;读 *** 作时保持高电平
output[7:0] data//LCD数据总线
// I/O寄存器
reg rs
reg en
reg[1:0] lcd_cs
reg[7:0] data
//内部寄存器
reg[3:0] state //状态机
reg[3:0] next_state
reg[20:0] div_cnt //分频计数器
reg[9:0] cnt //写 *** 作计数器
reg cnt_rst //写 *** 作计数器复位信号
wire[7:0] showdata //要显示的数据
reg[1:0] cs_r
reg [2:0] page_addr
reg [5:0] row_addr
//内部网线
wire clk_div//分频时钟
wire clk_divs
wire page_done //写一行数据完成标志位
wire frame_done //写一屏数据完成标志位
wire left_done
//状态机参数
parameter idle =4'b0000,
setbase_1=4'b0001,
setbase_2=4'b0011,
setmode_1=4'b0010,
setmode_2=4'b0110,
SETpage_addr_1=4'b0111,
SETpage_addr_2=4'b0101,
SETrow_addr_1 =4'b1101,
SETrow_addr_2 =4'b1111,
write_right_1 =4'b1110,
write_right_2 =4'b1010,
write_nextpage_1 =4'b1011,
write_nextpage_2 =4'b1001,
wr_data_1 =4'b0100,
wr_data_2 =4'b1100
// set_1=4'b1000
//******************************代码开始*********************************
assign rw = 1'b0 //对LCD始终为写 *** 作
//时钟分频
always@(posedge clock or negedge rst_n)
begin
if(!rst_n)
div_cnt <= 0
else
div_cnt <= div_cnt+1'b1
end
assign clk_div = (div_cnt[15:0] == 20'h7fff)
//状态机转向
always@(posedge clock or negedge rst_n)
begin
if(! rst_n)
state <= idle
else if(clk_div)
state <= next_state
end
//************************状态机逻辑*********************************
always@(state or page_done or left_done or frame_done or cnt or showdata or page_addr or row_addr or cs_r)
begin
rs <= 1'b0
en <= 1'b0
lcd_cs <= cs_r
cnt_rst <= 1'b0
data <= 8'h0
case(state)
idle:
begin
next_state <= setbase_1
cnt_rst <= 1'b1
end
//**************************初始化LCD********************************
setbase_1: //基本指令 *** 作
begin
lcd_cs <= 2'b11
next_state <= setbase_2
data <= 8'hc0
en <= 1'b1
end
setbase_2:
begin
lcd_cs <= 2'b11
next_state <= setmode_1
data <= 8'hc0
end
//******************************************************************
setmode_1:
begin
lcd_cs <= 2'b11
next_state <= setmode_2
data <= 8'h3f
en <=1'b1
end
setmode_2:
begin
next_state <= SETpage_addr_1
data <= 8'h3f
end
//******************************************************************
SETpage_addr_1: //设置页地址
begin
next_state <= SETpage_addr_2
data <=
en <= 1'b1
end
SETpage_addr_2:
begin
next_state <= SETrow_addr_1
data <=
end
SETrow_addr_1: //设置列地址
begin
next_state <= SETrow_addr_2
data <=
en <= 1'b1
end
SETrow_addr_2:
begin
next_state <= wr_data_1
data <=
end
//******************************************************************
/*
write_right_1: //写完左半屏64个,换为右半屏显示
begin
next_state <=write_right_2
row_addr <= 0
end
write_right_2:
begin
next_state <= SETpage_addr_1
end
//******************************************************************
write_nextpage_1: //写完全一行128个
begin
next_state <=write_nextpage_2
row_addr <= 0
end
write_nextpage_2:
begin
next_state <= SETpage_addr_1
end
*/
//******************************************************************
wr_data_1: //写数据到图形显示区
begin
next_state <= wr_data_2
rs <= 1'b1
en <= 1'b1
data <= showdata
end
wr_data_2:
begin
rs <= 1'b1
data <= showdata
if(left_done) //写完左半屏数据64个
begin
if(page_done) //写完一页数据128个
begin
if(frame_done) //写完一屏数据(8页)
next_state <= idle
else
// next_state <= write_nextpage_1
next_state <= SETpage_addr_1
end
else
// next_state <= write_right_1
next_state <= SETpage_addr_1
end
else
next_state <= wr_data_1
end
default: next_state <= idle
endcase
end
//********************************************************************
always@(posedge clock)
begin
if(clk_div)
begin
if(cnt_rst)
begin
cnt <= 0
end
else if(state == wr_data_2)
begin
cnt <= cnt+1'b1
end
end
end
//****************************************************
always@(posedge clock or negedge rst_n)
if(!rst_n)
begin
cs_r <= 2'b01
page_addr <= 0
end
else
if(clk_div &&(state == wr_data_2))
if(page_done)//
begin
cs_r <= 2'b01
page_addr <= page_addr + 1'b1//一页写完时写下一页
end
else
if(left_done)
begin
cs_r <= 2'b10
end
//*********************************************************************
//********************************************************************
assign left_done = (cnt[5:0] == 6'd63) //写完左半屏数据64个
assign page_done = (cnt[6:0] == 7'd127) //写完一页数据128个
assign frame_done = (cnt[9:4] == 7'h3f) //写完一屏数据
//***********************************************************************
//*******************************************************************
//调用ROM(图片数据)
rom rom(.address(cnt+'d8),.clock(clock),.q(showdata))
endmodule
开发板例程 自己看吧
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)