打印
[DSP编程]

DSP28335驱动LCD12864,程序改了三天了就是不能显示求大神指点

[复制链接]
4127|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 a939561900 于 2015-6-23 13:52 编辑

//###########################################################################
// LCD12864液晶显示程序
//###########################################################################

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// Prototype statements for functions found within this file.
void delay_loop(Uint32);
void Gpio_select(void);

void write_byte(Uint16 x);    //写8位数据
void lcd_write_cmd(Uint16);   //lcd 命令写
void lcd_write_data(Uint16);  //lcd 数据写
Uint16 lcd_read_data(void);   //lcd 数据读
void lcd_set_dot(unsigned char x, unsigned char y);

#define  BASIC_SET   0x30           //基本指令集  00110000
#define  EXTEND_SET  0x34           //扩展指令集  00110100
#define  DRAW_ON     0x36           //绘图显示开  00110110
#define  DRAW_OFF    0x34           //绘图显示关  00110100
#define  execute_72us    delay_loop(400)     //执行时间
#define  SCLK_quarter    delay_loop(40)       //四分之一SCLK时钟 SCLK是LCD串行通信时钟
#define  SCLK_half       delay_loop(80)       //二分之一SCLK时钟 SCLK是LCD串行通信时钟

#define CS_1        GpioDataRegs.GPADAT.bit.GPIO5=1             //GPIO5作为CS   
#define CS_0        GpioDataRegs.GPADAT.bit.GPIO5=0             //GPIO5作为CS   
#define SCLK_1      GpioDataRegs.GPADAT.bit.GPIO4=1             //GPIO4作为SCLK
#define SCLK_0      GpioDataRegs.GPADAT.bit.GPIO4=0             //GPIO4作为SCLK
#define SDATA_OUT   GpioCtrlRegs.GPADIR.bit.GPIO2=1             //GPIO2作为SDATA  
#define SDATA_IN    GpioCtrlRegs.GPADIR.bit.GPIO2=0             //GPIO2作为SDATA
#define SDATA       GpioDataRegs.GPADAT.bit.GPIO2
#define RST_1       GpioDataRegs.GPADAT.bit.GPIO3=1             //GPIO3做RST
#define RST_0       GpioDataRegs.GPADAT.bit.GPIO3=0             //GPIO3做RST  

#define uchar unsigned char
#define uint  Uint16

uchar AC_TABLE[]={
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,      //第一行汉字位置
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,      //第二行汉字位置
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,      //第三行汉字位置
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,      //第四行汉字位置
};

Uint16 sign[]={
0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,
0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,
};
uchar  str2[]="合肥零零电子科技";
uchar  str1[]="黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。";
Uint16  bmp1[];

Uint16 Key = 1;

/******************************************************************************************
* 函数名称    :Delay
******************************************************************************************/
void Delay(uint MS)
{
     uchar us,usn;
     while(MS!=0)            //for 12M
      {
         usn = 2;
         while(usn!=0)
          {
            us = 0xf5;
            while (us!=0)
             {
               us--;
             };
            usn--;
           }
         MS--;
      }
}
/******************************************************************************************
* 函数名称    :DelayKey
******************************************************************************************/
void DelayKey(uint Second , uint MS100)
{                              //输入精确到0.1S,是用","
     uint i;
     for(i=0;i<Second*100+MS100*10;i++)
     {
           if(Key==0)
           {
                 Delay(20);
                 while(Key==0)
                   {
                           Delay(20);
                   }
                 break;
           }
           else Delay(10);
     }
}

/******************************************************************************************
* 函数名称    :LcmInit
******************************************************************************************/
void LcmInit( void )
{
     lcd_write_cmd(0x30);      //8BitMCU,基本指令集合
     lcd_write_cmd(0x03);      //AC归0,不改变DDRAM内容
     lcd_write_cmd(0x0C);      //显示ON,游标OFF,游标位反白OFF
     lcd_write_cmd(0x01);      //清屏,AC归0
     lcd_write_cmd(0x06);      //写入时,游标右移动
}

/******************************************************************************************
* 函数名称    :LcmClearTXT
* 功能描述    :文本区清RAM函数
******************************************************************************************/
void LcmClearTXT( void )
{
     uchar i;
     lcd_write_cmd(0x30);      //8BitMCU,基本指令集合
     lcd_write_cmd(0x80);      //AC归起始位
     for(i=0;i<64;i++)
     lcd_write_data(0x20);
}

/******************************************************************************************
* 函数名称    :LcmClearBMP
* 功能描述    :图形区清RAM函数
******************************************************************************************/
void LcmClearBMP( void )
{
     uchar i,j;
     lcd_write_cmd(0x34);      //8Bit扩充指令集,即使是36H也要写两次
     lcd_write_cmd(0x36);      //绘图ON,基本指令集里面36H不能开绘图
     for(i=0;i<32;i++)            //12864实际为256x32
     {
           lcd_write_cmd(0x80|i);      //行位置
           lcd_write_cmd(0x80);      //列位置
           for(j=0;j<32;j++)            //256/8=32 byte
                lcd_write_data(0);
     }
}
/******************************************************************************************
* 函数名称    :PutStr
******************************************************************************************/
void PutStr(uchar row,uchar col,uchar *puts)
{
     lcd_write_cmd(0x30);      //8BitMCU,基本指令集合
     lcd_write_cmd(AC_TABLE[8*row+col]);      //起始位置
     while(*puts != '\0')      //判断字符串是否显示完毕
     {
           if(col==8)            //判断换行
           {            //若不判断,则自动从第一行到第三行
                 col=0;
                 row++;
           }
           if(row==4) row=0;      //一屏显示完,回到屏左上角
           lcd_write_cmd(AC_TABLE[8*row+col]);
           lcd_write_data(*puts);      //一个汉字要写两次
           puts++;
           lcd_write_data(*puts);
           puts++;
           col++;
     }
}
/******************************************************************************************
* 函数名称    :PutSign
******************************************************************************************/
void PutSign(uchar row,uchar col,Uint16 *sign)
{
     Uint16 i=0;
     lcd_write_cmd(0x30);      //8BitMCU,基本指令集合
     lcd_write_cmd(AC_TABLE[8*row+col]);      //起始位置 sign_TABLE[8*row+col]
     for(i=0;i<32;i++)      //判断字符串是否显示完毕
     {
           if(col==8)            //判断换行 半宽符号,所以一行16个
           {            //若不判断,则自动从第一行到第三行
                col=0;
                row++;
           }
           if(row==4) row=0;      //一屏显示完,回到屏左上角
           lcd_write_cmd(AC_TABLE[8*row+col]);
           lcd_write_data(*sign);      //一个汉字要写两次
           sign++;
           col++;
     }


}
/******************************************************************************************
* 函数名称    :PutBMP
******************************************************************************************/
void PutBMP(Uint16 *puts)
{
     uint x=0;
     uchar i,j;
     lcd_write_cmd(0x34);      //8Bit扩充指令集,即使是36H也要写两次
     lcd_write_cmd(0x36);      //绘图ON,基本指令集里面36H不能开绘图
     for(i=0;i<32;i++)            //12864实际为256x32
     {
           lcd_write_cmd(0x80|i);      //行位置
           lcd_write_cmd(0x80);      //列位置
           for(j=0;j<16;j++)      //256/8=32 byte
           {            //列位置每行自动增加
                 lcd_write_data(((puts[x]&0xFF00)>>8));
                 lcd_write_data((puts[x]&0x00FF));
                 x++;
           }
     }
}
/******************************************************************************************
* 函数名称    :DisplayDots
******************************************************************************************/
void DisplayDots(uchar DotByte)
{
     uchar i,j;
     lcd_write_cmd(0x34);      //8Bit扩充指令集,即使是36H也要写两次
     lcd_write_cmd(0x36);      //绘图ON,基本指令集里面36H不能开绘图
     for(i=0;i<32;i++)            //12864实际为256x32
     {
           lcd_write_cmd(0x80|i);      //行位置
           lcd_write_cmd(0x80);      //列位置
           for(j=0;j<32;j++)      //256/8=32 byte
           {            //列位置每行自动增加
              lcd_write_data(DotByte);                  
           }
           DotByte=~DotByte;
     }
}

/******************************************************************************************/

void main(void)
{

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initalize GPIO:
           Gpio_select();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
   InitPieVectTable();



   RST_0;
   Delay(30);

   RST_1;
   LcmInit();
   LcmClearTXT();
   LcmClearBMP();

   for(;;)
   {   

        // lcd_set_dot(2,2);
           //显示图像
           LcmClearTXT();
       PutBMP(bmp1);
       DelayKey(20,5);
       /*
       //全屏间隔显示点
       DisplayDots(0x55);
       DelayKey(1,5);

       //全屏间隔显示点            
       LcmClearTXT();
       DisplayDots(0xaa);
       DelayKey(1,5);

            
       */
       //全屏显示文字

                LcmClearBMP();
       DelayKey(15,5);
       PutStr(0,0,str1);
       DelayKey(30,5);
         //  PutSign(0,0,sign);
      /*
       LcmClearTXT();
       DelayKey(15,5);
       PutStr(0,0,str2);
       DelayKey(30,5);
            //全屏间隔显示半型符号            
       LcmClearTXT();
       PutSign(0,0,sign);
       DelayKey(30,5);
//            while(1); */
    }


}         


/******************************************************************************************
* 函数名称    :delay_loop
******************************************************************************************/
void delay_loop(Uint32 x)
{
    Uint32      i;
    for (i = 0; i < x; i++) {}
}
/******************************************************************************************
* 函数名称    :Gpio_select
******************************************************************************************/
void Gpio_select(void)
{
  EALLOW;
        GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;
        GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0;
        GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0;
        GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0;
           
    GpioCtrlRegs.GPAMUX1.bit.GPIO2=0;
    GpioCtrlRegs.GPAMUX1.bit.GPIO4=0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO3 =0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO5 =0;

    GpioCtrlRegs.GPADIR.bit.GPIO2=1;
    GpioCtrlRegs.GPADIR.bit.GPIO4=1;
        GpioCtrlRegs.GPADIR.bit.GPIO3=1;
        GpioCtrlRegs.GPADIR.bit.GPIO5=1;

  EDIS;   
}     
/******************************************************************************************
* 函数名称    :write_byte
******************************************************************************************/
void write_byte(Uint16 x)
{
        Uint16 i = 0;
        SDATA_OUT;
        SCLK_quarter;
        for(i=0;i<=7;i++)
        {
                SCLK_0;
                SCLK_quarter;
                SDATA=(0x1&((x)>>(7-i)));  //先把高位移出然后发送
                SDATA=(0x1&((x)>>(7-i)));
                SCLK_quarter;
                SCLK_1;                    //把时间改成上升沿锁存的
                SCLK_half;
                SCLK_0;
                SCLK_quarter;
        }
        SDATA=0;
}

/*void write_byte(Uint16 x)
{
        Uint16 i = 0;
        SDATA_OUT;
        for(i=0;i<=7;i++)
        {
                SCLK_0;
                SCLK_quarter;
                if((0x1&((x)>>(7-i)))==1)
                {
                        GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all|0x04000000;  //GPIO26输出1
                }
                else
                {
                        GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all&0xFBFFFFFF;  //GPIO26 输出0
                }
                SCLK_quarter;
                SCLK_1;                    //把时间改成上升沿锁存的
                SCLK_half;
                SCLK_0;
                SCLK_quarter;
        }
        SDATA=0;
}        
*/
/******************************************************************************************
* 函数名称    :read_byte
******************************************************************************************/
Uint16 read_byte(void)
{
        Uint16 i = 0;
        Uint16 data = 0;
        SDATA_IN;
        data=0;
        for(i=0;i<=7;i++)
        {
                SCLK_0;
                SCLK_quarter;
                SCLK_1;
                SCLK_quarter;
                if(SDATA)
                {
                   data= (data|(0x01<<(7-i)));  //注意!
                }
                SCLK_quarter;
                SCLK_0;
                SCLK_quarter;
        }
        return data;
}        
/******************************************************************************************
* 函数名称    :lcd_write_cmd
******************************************************************************************/
void lcd_write_cmd(Uint16 data)   //lcd 命令写
{
        Uint16 tmp1,tmp2;
        CS_1;
        delay_loop(40);
        tmp1= (data&0xF0);           //高四位
        tmp2= ((data&0x0F)<<4);      //低四位左移
        write_byte(0xF8); //0xF8 ==11111000 b 这个代表从MCU到LCD 并且是指令
        write_byte(tmp1);
        write_byte(tmp2);
        delay_loop(40);
        CS_0;
        execute_72us;
}
/******************************************************************************************
* 函数名称    :lcd_write_data
******************************************************************************************/
void lcd_write_data(Uint16 data)  
{
        Uint16 tmp1,tmp2;
        CS_1;
        delay_loop(40);
        tmp1= (data&0xF0);           //高四位
        tmp2= ((data&0x0F)<<4);      //低四位左移
        write_byte(0xFA); //0xFA ==11111010 b 这个代表从MCU到LCD 并且是数据
        write_byte(tmp1);
        write_byte(tmp2);
        delay_loop(40);
        CS_0;
        execute_72us;
}
/******************************************************************************************
* 函数名称    :lcd_read_data
******************************************************************************************/
Uint16 lcd_read_data(void)  
{
        Uint16 tmp1,tmp2,data;
        CS_1;
        write_byte(0xFE); //0xFA ==11111110 b 这个代表从MCU到LCD 并且是数据
        tmp1=read_byte();
        tmp2=read_byte();
        CS_0;
        execute_72us;
        data= (tmp1&0xF0);                  //高四位
        data= (data|((tmp2&0xF0)>>4));      //低四位
        return data;
}
/******************************************************************************************
* 函数名称    :lcd_set_dot
******************************************************************************************/
void lcd_set_dot(unsigned char x, unsigned char y)
{
    unsigned char x_byte, 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_ON);            //绘图显示打开
    lcd_write_cmd(0x80 + y_bit);        //先写垂直地址(最高位必须为1)
                                        //具体参照数据手册
    lcd_write_cmd(0x80 + x_byte + 8 * y_byte);   //水平坐标
                                                 //下半屏的水平坐标起始地址为0x88
                                                 //(+8*y_byte)就是用来确定
                                                 //在上半屏还是下半屏

    if (x_bit < 8)                               //绻鹸_bit位∮?
    {
        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));

    }  

    return ;

}

//===========================================================================
// No more.
//===========================================================================



QQ截图20150623134924.png (36.82 KB )

原理图

原理图

相关帖子

沙发
JY-DX-JY| | 2015-6-23 14:14 | 只看该作者
对照手册,用示波器看时序,延时准不准。

使用特权

评论回复
板凳
zhangmangui| | 2015-6-23 22:13 | 只看该作者
时序的问题    代码里不容易看出啊

使用特权

评论回复
地板
a939561900|  楼主 | 2015-6-24 22:01 | 只看该作者
zhangmangui 发表于 2015-6-23 22:13
时序的问题    代码里不容易看出啊

你好!感谢你的回答,那这个时序主要看那几个点呢? 还有就是那个延时大概要多长才合适呢?没找到合适的资料解释

使用特权

评论回复
5
a939561900|  楼主 | 2015-6-24 22:02 | 只看该作者
JY-DX-JY 发表于 2015-6-23 14:14
对照手册,用示波器看时序,延时准不准。

你好!感谢你的回答,那这个时序主要看那几个点呢? 还有就是那个延时大概要多长才合适呢?没找到合适的资料解释

使用特权

评论回复
6
JY-DX-JY| | 2015-6-25 09:43 | 只看该作者
要看你12864的驱动芯片。

使用特权

评论回复
7
zhangmangui| | 2015-6-25 21:53 | 只看该作者
a939561900 发表于 2015-6-24 22:01
你好!感谢你的回答,那这个时序主要看那几个点呢? 还有就是那个延时大概要多长才合适呢?没找到合适的资 ...

一定要看手册    通过示波器结合查看
如果不确定   建议设置慢一些   慢了不影响

使用特权

评论回复
8
jonyamyor| | 2015-6-30 00:12 | 只看该作者
前段时间,我也在做LCD12864的程序,刚开始也是不能显示,还在这里发过帖子,后来问题解决了,也就是时序问题,主要是看LCD写指令或数据用的时间,这里做好了基本就没问题,另外我发的帖子上也有说

使用特权

评论回复
9
a939561900|  楼主 | 2015-7-2 00:12 | 只看该作者
谢谢大家的回答!我换了一款海比邻的LCD,调通了,再次感谢大家!

使用特权

评论回复
10
ie谁是谁的谁| | 2016-3-29 13:58 | 只看该作者
a939561900 发表于 2015-7-2 00:12
谢谢大家的回答!我换了一款海比邻的LCD,调通了,再次感谢大家!

我最近也在调12864的程序  一直出问题不出显示  能请教吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

15

帖子

0

粉丝