打印

SPI总线如何驱动12864液晶,

[复制链接]
8414|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wang12zhe|  楼主 | 2013-5-23 10:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我的程序如下
/* 液晶演示程序JLX12864G-086,串行接口!
   驱动IC是:UC1701X或兼容的IC,比如ST7565R
   叶建人编写,6月27日,2012
   晶联讯电子:网址  http://www.jlxlcd.cn;
*/
#include <REG51xD2.H>
#include <intrins.h>
#include <Ctype.h>
sbit Up     =   P1^0;

sbit Left   =   P1^2;
sbit Right  =   P1^3;
sbit cs1    =   P0^0 ;                   //LCM片选信号端                                                                                         
sbit rs                =        P2^2;     //数据命令选择端口
sbit reset        =          P2^3;          //LCM复位
sbit SPISS  =   P1^1;       //SPI总线的从机选择脚  MCU使用
sbit sclk        =        P1^6;    //  SCK
sbit sid        =   P1^7;     //sid 就是 SDA,串行数据信号        端口MOSI
sbit LEDA        =        P0^1;        //背光控制,低电平点亮

unsigned char column;
unsigned char page;


void delay(unsigned int i);
void clear_screen();


unsigned char code zhuang1[]={
/*--  文字:  状  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x08,0x30,0x00,0xFF,0x20,0x20,0x20,0x20,0xFF,0x20,0xE1,0x26,0x2C,0x20,0x20,0x00,
0x04,0x02,0x01,0xFF,0x40,0x20,0x18,0x07,0x00,0x00,0x03,0x0C,0x30,0x60,0x20,0x00};

unsigned char  code tai1[]={
/*--  文字:  态  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x04,0x04,0x04,0x84,0x44,0x34,0x4F,0x94,0x24,0x44,0x84,0x84,0x04,0x00,0x00,
0x00,0x60,0x39,0x01,0x00,0x3C,0x40,0x42,0x4C,0x40,0x40,0x70,0x04,0x09,0x31,0x00};

unsigned char  code shi1[]={
/*--  文字:  使  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x20,0xF0,0x1C,0x07,0xF2,0x94,0x94,0x94,0xFF,0x94,0x94,0x94,0xF4,0x04,0x00,
0x00,0x00,0x7F,0x00,0x40,0x41,0x22,0x14,0x0C,0x13,0x10,0x30,0x20,0x61,0x20,0x00};

unsigned char  code yong1[]={
/*--  文字:  用  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,
0x80,0x40,0x30,0x0F,0x02,0x02,0x02,0x02,0xFF,0x02,0x02,0x42,0x82,0x7F,0x00,0x00};



unsigned char  code mao_hao[]={
/*--  文字:  : (冒号) --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00};

unsigned char  code num0[]={
/*--  文字:  0  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00
};
char code num1[]={
/*--  文字:  1  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00
};
char code num2[]={
/*--  文字:  2  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00
};
unsigned char  code num3[]={
/*--  文字:  3  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00
};
char code num4[]={
/*--  文字:  4  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00
};

unsigned char  code num5[]={
/*--  文字:  5  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00
};

unsigned char  code num6[]={
/*--  文字:  6  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00
};
unsigned char  code num7[]={
/*--  文字:  7  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00
};
unsigned char  code num8[]={
/*--  文字:  8  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00
};

unsigned char  code num9[]={
/*--  文字:  9  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00
};

unsigned char  code empty[]=
{
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};


void SPI_init()
{
        SPDAT = 0;                                   //清空数据缓存
        SPISS=1;                       /* enable master */  //片选信号  主机片选信号必须为高电平
        SPCON |= 0x10;                /* Master mode */
        SPCON |= 0x01;                /* Fclk Periph/64 */
        SPCON &= ~0x08;               /* CPOL=0; transmit mode example */
   /*因为使用的12864是上升沿写入数据,所以注意CPOL 和CPHA的配置*/
        SPCON &= ~0X04;                                  /* CPHA=0; transmit mode example */
        SPCON &=~0x20;                                  /* Cleared to enable SS in both Master and Slave modes.*/
        IEN1 |= 0x04;                 /* enable spi interrupt */
        SPCON |= 0x40;                /* run spi   SPEN=1 */
        EA=1;                         /* enable interrupts */
}


unsigned char SPIS_Transfer(unsigned char dat)
{
    SPDAT = dat;                //trigger SPI send
    while (!(SPSTA&0X80));             //wait send complete
    return SPDAT;               //return received SPI data
}

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

void Send_byte(unsigned char Byte)
{
    SPIS_Transfer(Byte);
}
/***********写指令到LCD模块******************************************/
void Transfer_command(unsigned char  send_cmd)
{
          cs1=0;
          rs=0;

   Send_byte(send_cmd);               // 发送起始信号 第1字节-格式:1111ABC
   delay(5);                            // 延时是必须的


}
/*写数据到LCD模块*/
void Transfer_data(int send_data)
{
        cs1=0;
        rs=1;
  Send_byte(send_data);               // 发送起始信号 第1字节-格式:1111ABC
  delay(5);   
   
}
/*延时*/
void delay(unsigned int i)               
{
unsigned int j,k;
for(j=0;j<i;j++)
   for(k=0;k<110;k++);
}

/*LCD模块初始化*/
void initial_lcd()
{
        cs1=0;
          reset=0;        /*低电平复位*/
          delay(100);
          reset=1;                    /*复位完毕*/
          delay(20);        
        Transfer_command(0xe2);         /*软复位*/
        delay(5);
        Transfer_command(0x2c);  /*升压步聚1*/
        delay(5);       
        Transfer_command(0x2e);  /*升压步聚2*/
        delay(5);
        Transfer_command(0x2f);  /*升压步聚3*/
        delay(5);
        Transfer_command(0x23);  /*粗调对比度,可设置范围0x20~0x27*/
        Transfer_command(0x81);  /*微调对比度*/
        Transfer_command(0x28);  /*0x1a,微调对比度的值,可设置范围0x00~0x3f*/
        Transfer_command(0xa2);  /*1/9偏压比(bias)*/
        Transfer_command(0xc8);  /*行扫描顺序:从上到下*/
        Transfer_command(0xa0);  /*列扫描顺序:从左到右*/
        Transfer_command(0x40);  /*起始行:第一行开始*/
        Transfer_command(0xaf);  /*打开显示*/
        clear_screen();            //clear all dots
        cs1=1;
}

void lcd_address(unsigned char  page,unsigned char  column)
{
        cs1=0;
        column=column-1;                                                          //我们平常所说的第1列,在LCD驱动IC里是第0列。所以在这里减去1.
        page=page-1;
        Transfer_command(0xb0+page);                                   //设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/
        Transfer_command(((column>>4)&0x0f)+0x10);        //设置列地址的高4位
        Transfer_command(column&0x0f);                                //设置列地址的低4位
}

/*全屏清屏,实际上是向每个点送数据0*/
void clear_screen()
{
        unsigned char i,j;
        cs1=0;
        for(i=0;i<9;i++)
        {
                lcd_address(1+i,1);
                for(j=0;j<132;j++)   //
                {
                        Transfer_data(0x00);
                }
        }
        cs1=1;
}

/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/
void display_graphic_16x16(unsigned char  page,unsigned char  column,unsigned char  *dp)
{
        unsigned char  i,j;

        cs1=0;
        for(j=0;j<2;j++)
        {
                lcd_address(page+j,column);
                for (i=0;i<16;i++)
                {       
                        Transfer_data(*dp);                /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
                        dp++;
                }
        }
        cs1=1;
}

/*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/
void display_graphic_8x16(unsigned char  page,unsigned char  column,unsigned char  *dp)
{
        unsigned char  i,j;
        cs1=0;       
        for(j=0;j<2;j++)
        {
                lcd_address(page+j,column);
                for (i=0;i<8;i++)
                {       
                        Transfer_data(*dp);                                        /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/
                        dp++;
                }
        }
        cs1=1;
}

//分\秒闪烁,time表示分\秒的数据
void blink_graphic_8x16(unsigned char  page,unsigned char  column,unsigned char  *dp)
{
        unsigned char  delay_counter;                                                        //延时计数器
        while(Right==1)                                                                        //我的主板的按键是接在某某I/O口与地之间
        {
                delay_counter=0;                                                        //延时计数器归零
                display_graphic_8x16(page,column,empty);          //显示首位空
                while(Right==1&&delay_counter<5)
                {       
                        delay(100);                                                      //延时100 ms左右再去扫描键盘,如此反复多次
                        delay_counter++;
                }
                display_graphic_8x16(page,column,dp);                //显示时间
                delay_counter=0;                                                        //延时计数器归零
                while(Right==1&&delay_counter<5)
                {       
                        delay(100);                                                      //延时100 ms左右再去扫描键盘,如此反复多次
                        delay_counter++;
                }
                delay_counter=0;                                                        //延时计数器归零
        }
}

void keyscan()
{
  if(Up == 0){
    page--;
        INT0=0;
   if(page==255)page=7;   // 定义为unsgined char 0 再减一等于255
  }
  /*
  if(Down == 0){
  page++;
   T1 = 1;       
   if(page==7)page=0;
  }
  */
  if(Left == 0){
    column--;
   if(column==255)column=128;          // // 定义为unsgined char 0 再减一等于255
  }
  if(Right == 0){
  column++;
   if(column==128)column=0;
  }


}
void main(void)
{
        LEDA=0;       
        SPI_init();
    delay(5);
        initial_lcd();

        page  = 3;
        column= 0;

         while(1)
        {
          //         clear_screen();            //clear all dots
                display_graphic_16x16(page,column,zhuang1);                 /*在第5页,第1列显示单个汉字"状"*/
                display_graphic_16x16(page,(column+16),tai1);                 /*在第5页,第17列显示单个汉字"态"*/
                display_graphic_8x16(page,(column+16*2),mao_hao);         /*在第5页,第25列显示单个字符":"*/
                display_graphic_16x16(page,(column+16*2+8),shi1);         /*在第5页,第41列显示单个汉字"使"*/
                display_graphic_16x16(page,(column+16*3+8),yong1);        /*在第5页,第49列显示单个汉字"用"*/
                display_graphic_8x16(page,(column+88),num0);                         /*在第5页,第89列显示单个数字"0"*/
                display_graphic_8x16(page,(column+88+8*1),num0);                 /*在第5页,第97列显示单个数字"0"*/
                display_graphic_8x16(page,(column+88+8*2),mao_hao);         /*在第5页,第105列显示单个字符":"*/
                display_graphic_8x16(page,(column+88+8*3),num0);                 /*在第5页,第113列显示单个数字"0"*/
                display_graphic_8x16(page,(column+88+8*4),num0);                 /*在第5页,第121列显示单个数字"0"*/
            
                blink_graphic_8x16(page,(column+88+8*4),num0);                //光标闪烁

                 
       
        }
}


/**
* FUNCTION_PURPOSE:interrupt
* FUNCTIO N_INPUTS: void
* FUNCTION_OUTPUTS: transmit_complete is software transf
*/
void it_SPI(void) interrupt 9 /* interrupt address is 0x004B*/
{
        SPCON |= 0x40;                /* run spi   SPEN=1 */
        SPCON |= 0x10;                /* Master mode */       
        switch( SPSTA )         /* read and clear spi status reGISTER*/
        {
        case 0x80:
         
                 //serial_data=SPDAT;   /* read receive data */
                 //transmit_completed=1;/* set software flag */
         break;
        case 0x10:
                 /* put here for mode fault tasking */
        break;
        case 0x40:
                 /* put here for overrun tasking */
        break;
        }
}



确实能驱动12864了,但是程序里有
unsigned char SPIS_Transfer(unsigned char dat)
{
    SPDAT = dat;                //trigger SPI send
    while (!(SPSTA&0X80));             //wait send complete
    return SPDAT;               //return received SPI data
}
这样的一段代码
但是这个 while (!(SPSTA&0X80));  会导致传输变慢,
想在ISP中断里处理,怎么办呀


求大神帮助


相关帖子

沙发
NE5532| | 2013-5-23 12:20 | 只看该作者
开SPI发送完成中断就可以了,另外SPI的传输速度很快,如果不会影响到其它业务,这种查询方式是最简单的。除非有必要,不要自己弄复杂了。

使用特权

评论回复
板凳
wang12zhe|  楼主 | 2013-5-23 13:40 | 只看该作者
NE5532 发表于 2013-5-23 12:20
开SPI发送完成中断就可以了,另外SPI的传输速度很快,如果不会影响到其它业务,这种查询方式是最简单的。除 ...

开SPI中断,但是在SPI中断里怎么操作呀,是这样的,我们的一个项目需要,想在SPI传输的过程中不去等待,而是能让MCU去处理其他事情,这样怎么做的呀

使用特权

评论回复
地板
NE5532| | 2013-5-23 14:18 | 只看该作者
中断,进一次SPI发送中断,填充发送下一字节数据,另外需要一个全局变量保存状态,否则每次进中断看到的情况都相同,不知道什么时候发送完成。想是可以的,但是要想清楚是否必要,只是个善意提醒,避免做了N多工作以后发现根本没必要。

使用特权

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

本版积分规则

101

主题

205

帖子

1

粉丝