现在的位置: 首页 > 综合 > 正文

SPI总线驱动12864

2014年10月05日 ⁄ 综合 ⁄ 共 11006字 ⁄ 字号 评论关闭

以前使用12864液晶时使用单片机IO口模拟SPI总线,导致显示程序耗时多,频繁刷新屏幕有闪烁。STC新的单片机(比如STC12C5A60S2)自带有SPI总线接口,用SPI硬件驱动LCD无疑是一个很好的选择。做过LCD功能扩展的朋友们知道,LCD驱动程序的核心就是SPI通讯部分,我们只用改写这一部分程序就可以,其他程序不变。这里我参考了STC的数据手册和网友的一个程序,还有一个小问题就是丛机的片选端在STC的头文件中是P1.4,但给的演示程序中改为了P1.3,这点要注意。可以发现使用SPI总线驱动时执行效率很高,使用单片机口线最少,十分便于程序编写。

 

//========================================代码区==========================================//

//#include <STC_NEW_8051.H>
#include "STC12C5A.h"
//============================================================================================================
#define uint unsigned int
#define uchar unsigned char

#define x1    0x80
#define x2    0x88
#define y     0x80
//引脚定义
sbit    LCD_CS    =P1^4;        // 片选 高电平有效 单片LCD使用时                     可固定高电平
//数据 LCD_SID   =P1^5;
//时钟 LCD_CLK   =P1^7;
sbit    LCD_PSB   =P3^5;        // 低电平时表示用串口驱动,                          可固定低电平
sbit    LCD_RST   =P3^6;        // LCD复位,LCD模块自带复位电路。                    可不接
//sbit  LCD_BACK  =P2^6;        // LCD背光控制

//sbit SPISS      =   P1^3;       //SPI总线的从机选择脚
/*此处参考了宏晶的SPI主机例子,将管脚从P14改为P13,具体原因未知,待查*/
//=========================================================================
uchar code tab1[]={
"人生若只是初见,"
"何事秋风悲画扇。"
"等闲变却故人心,"
"却道故人心易变。"
};
//----------------------------------开机图片-----------------------------------
uchar code logo[]=
{
/*----  图片文件来自:【C:/Documents and Settings/Administrator/桌面/李孟阳.JPG】  ----*/
/*----  图片宽度:128     图片高度:64  ----*/
/*----  本数据文件建立日期:202011-5-7;  建立时间:6:49:10  ----*/
/*----  本数据文件由PICtoCODE【图片数据生成器】V1.0自动生成!  ----*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20,
0x10, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x30, 0x00, 0x63, 0x60, 0x03, 0xB7, 0xE0, 0x00, 0x18, 0x10,
0x10, 0xFE, 0x1F, 0xC1, 0xE0, 0x06, 0x60, 0x00, 0x63, 0x38, 0x0F, 0xBC, 0x00, 0x03, 0x18, 0x10,
0x10, 0xCE, 0x18, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xE3, 0x00, 0x0D, 0xB1, 0x80, 0x3E, 0x38, 0x10,
0x11, 0xC6, 0x18, 0xE0, 0xC0, 0x00, 0x70, 0x00, 0xDB, 0xE0, 0x0D, 0xBD, 0x80, 0x00, 0x30, 0x10,
0x11, 0xC6, 0x18, 0xE0, 0xC0, 0x1F, 0xFC, 0x01, 0x9F, 0x80, 0x0F, 0x37, 0x80, 0x00, 0x3F, 0x10,
0x10, 0xE0, 0x18, 0xC0, 0xC0, 0x0C, 0x30, 0x03, 0xBF, 0x70, 0x0F, 0x37, 0x80, 0x1F, 0xF3, 0x10,
0x10, 0x78, 0x19, 0xC0, 0xC0, 0x0C, 0x30, 0x03, 0xE1, 0xC0, 0x0F, 0x33, 0x01, 0xFC, 0x37, 0x10,
0x10, 0x3C, 0x1F, 0x00, 0xC0, 0x0F, 0xE0, 0x00, 0xCF, 0xB0, 0x1F, 0xF3, 0x80, 0x18, 0x77, 0x10,
0x10, 0x0E, 0x18, 0x00, 0xC0, 0x00, 0x00, 0x01, 0xF9, 0xB0, 0x18, 0xF7, 0x80, 0x1B, 0x66, 0x10,
0x11, 0x86, 0x18, 0x00, 0xC0, 0x01, 0x87, 0x03, 0xC0, 0xE0, 0x03, 0xFC, 0xC0, 0x33, 0x66, 0x10,
0x11, 0x86, 0x18, 0x00, 0xC0, 0x6C, 0xC3, 0x80, 0x00, 0xC0, 0x3E, 0xF0, 0xC0, 0x7F, 0xC6, 0x10,
0x11, 0x8E, 0x18, 0x00, 0xC0, 0x6C, 0x19, 0x80, 0x73, 0xE0, 0x31, 0xF0, 0xE0, 0x60, 0xC6, 0x10,
0x11, 0xFC, 0x1C, 0x01, 0xE0, 0x66, 0x0C, 0x07, 0xCE, 0x7C, 0x07, 0xBF, 0xF0, 0x01, 0xBE, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8E, 0x03, 0x00, 0x3C, 0x03, 0x80, 0x00, 0x03, 0x1C, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x18, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC6, 0x00, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x66, 0x01, 0xC3, 0x00, 0x0E, 0x0C, 0x00, 0x00, 0x70, 0x10,
0x10, 0xE0, 0x0F, 0xC3, 0xF0, 0x0C, 0x7F, 0xC0, 0xC3, 0x00, 0x07, 0x01, 0xC0, 0x0F, 0xE0, 0x10,
0x10, 0xC0, 0x18, 0xC3, 0x38, 0x0D, 0xFC, 0x00, 0xC3, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x10,
0x10, 0xC0, 0x38, 0xC3, 0x18, 0x0C, 0x6C, 0x00, 0xC3, 0xF0, 0x01, 0xC0, 0xC0, 0x00, 0x00, 0x10,
0x10, 0xC0, 0x38, 0x03, 0x1C, 0x3E, 0xFF, 0x80, 0xFF, 0xE0, 0x39, 0xBE, 0x00, 0x00, 0x0E, 0x10,
0x10, 0xC0, 0x30, 0x03, 0x1C, 0x6C, 0xE3, 0x03, 0xC3, 0x60, 0x1C, 0x18, 0x00, 0x07, 0xFF, 0x90,
0x10, 0xC0, 0x30, 0x03, 0x1C, 0x1C, 0xFB, 0x00, 0xC3, 0x60, 0x00, 0x7F, 0x80, 0xFD, 0x80, 0x10,
0x10, 0xC0, 0x30, 0x03, 0x1C, 0x1E, 0xC3, 0x00, 0xC6, 0xFC, 0x00, 0xD9, 0x80, 0x01, 0x80, 0x10,
0x10, 0xC0, 0x30, 0x03, 0x1C, 0x3F, 0x7E, 0x00, 0xFF, 0x80, 0x06, 0xFD, 0x80, 0x01, 0xB8, 0x10,
0x10, 0xC0, 0x38, 0x03, 0x18, 0x6C, 0x38, 0x00, 0xC7, 0x00, 0x0C, 0xDB, 0x00, 0x31, 0x9C, 0x10,
0x10, 0xC6, 0x38, 0xC3, 0x38, 0xCC, 0xFF, 0xC3, 0x8D, 0x80, 0x0C, 0x7F, 0x00, 0x31, 0x8E, 0x10,
0x10, 0xC6, 0x18, 0xC3, 0x31, 0x8D, 0xBC, 0x07, 0x0C, 0xC0, 0x3C, 0x00, 0x00, 0x31, 0x86, 0x10,
0x10, 0xFE, 0x0D, 0x83, 0xE0, 0x0C, 0x36, 0x00, 0x18, 0x70, 0x18, 0x77, 0x00, 0x07, 0x80, 0x10,
0x08, 0x00, 0x07, 0x00, 0x00, 0x0C, 0x67, 0x00, 0x30, 0x3C, 0x00, 0xC3, 0x80, 0x03, 0x80, 0x20,
0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC3, 0xC0, 0x60, 0x00, 0x01, 0x81, 0x80, 0x00, 0x00, 0x20,
0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x00,
0x00, 0xE3, 0x8C, 0x30, 0x3C, 0x0E, 0x1B, 0x0F, 0x0F, 0xC0, 0x03, 0xE0, 0x7C, 0x1E, 0x20, 0x00,
0x01, 0xA2, 0x8C, 0x70, 0x48, 0x18, 0x1F, 0x09, 0x0C, 0xC0, 0x05, 0xC0, 0x1A, 0x0D, 0xF0, 0x00,
0x00, 0x26, 0xC4, 0x10, 0xFC, 0x1C, 0x1B, 0x01, 0x0C, 0xC0, 0x03, 0xB0, 0xFF, 0x0D, 0xB0, 0x00,
0x00, 0x66, 0xC4, 0x10, 0x6B, 0x06, 0x1F, 0x03, 0x0F, 0xC0, 0x07, 0xD8, 0x18, 0x0F, 0xF0, 0x00,
0x00, 0x46, 0xC4, 0x11, 0xFF, 0x86, 0x11, 0x02, 0x0C, 0xC0, 0x00, 0xB0, 0x1E, 0x19, 0xB0, 0x00,
0x00, 0x82, 0xC4, 0x10, 0x08, 0x06, 0x11, 0x02, 0x0F, 0xC0, 0x0F, 0xF8, 0x7E, 0x19, 0xF0, 0x00,
0x01, 0xE3, 0x8C, 0x30, 0x08, 0x1C, 0x33, 0x06, 0x0C, 0x80, 0x00, 0xC0, 0x7E, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x23, 0x00, 0x00, 0x80, 0x01, 0x81, 0xFF, 0x90, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

};

#define MASTER                  //define:master undefine:slave

void InitSPI()
{
    SPDAT = 0;                  //initial SPI data
    SPSTAT = SPIF | WCOL;       //clear SPI status
#ifdef MASTER
    SPCTL = SPEN | MSTR | CPHA | CPOL | SPSPEEDH;               //master mode
#else
    SPCTL = SPEN;               //slave mode
#endif
}

uchar SPISwap(uchar dat)
{
#ifdef MASTER
    SPISS = 1;                  //pull low slave SS
#endif
    SPDAT = dat;                //trigger SPI send
    while (!(SPSTAT & SPIF));   //wait send complete
    SPSTAT = SPIF | WCOL;       //clear SPI status
#ifdef MASTER
    SPISS = 0;                  //push high slave SS
#endif
    return SPDAT;               //return received SPI data
}

//=========================================================================

void Delay(uint Number)
{
  uint i,j;

  for (i=0; i<Number; i++)
  {
      for(j=0; j<10; j++)
        {
   ;
  }
 }
}

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

void Send_byte(uchar Byte)
{
    SPISwap(Byte);
}
/*****************************************************/

void WriteCommandLCM(uchar WCLCM)
{
   uchar Start_data,Hdata,Ldata;

 Start_data = 0xf8;                     // 写指令 11111000
 
   Hdata = WCLCM&0xf0;                  // 取高四位   DDDD0000
   Ldata = (WCLCM << 4) & 0xf0;         // 取低四位   0000DDDD

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

   Send_byte(Hdata);                    // 发送高四位   第2字节-格式:DDDD0000
   Delay(1);                            // 延时是必须的

   Send_byte(Ldata);                    // 发送低四位   第3字节-格式:0000DDDD
   Delay(1);                            // 延时是必须的
}
/*****************************************************/

void WriteDataLCM(uchar WDLCM)
{
   uchar Start_data,Hdata,Ldata;

    Start_data = 0xfa;                   // 写数据 11111010

   Hdata = WDLCM & 0xf0;                 // 取高四位   DDDD0000
   Ldata = (WDLCM << 4) & 0xf0;          // 取低四位   0000DDDD

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

   Send_byte(Hdata);                     // 发送高四位   第2字节-格式:DDDD0000
   Delay(1);                             // 延时是必须的

   Send_byte(Ldata);                     // 发送低四位   第3字节-格式:0000DDDD
   Delay(1);                             // 延时是必须的
}

/*****************************************************/
void Lcdinit(void) 
{
   Delay(10);                              // 启动等待,等LCM讲入工作状态
   LCD_PSB = 0;                            // 串口驱动模式
   LCD_RST = 0;

    Delay(1);
    LCD_RST = 1;                           // 复位LCD
    LCD_CS = 1;                            // 片选

   WriteCommandLCM(0x30);                  // 8 位介面,基本指令集
   WriteCommandLCM(0x0c);                  // 显示打开,光标关,反白关
   WriteCommandLCM(0x01);                  // 清屏,将DDRAM的地址计数器归零 
}
/*---------------显示汉字或字符----------------*/
void chn_disp(uchar code *chn)
{
  uchar i,j;
  WriteCommandLCM(0x30);
  WriteCommandLCM(0x80);
  for (j=0;j<4;j++)
  {
    for (i=0;i<16;i++)
    WriteDataLCM(chn[j*16+i]);
  }
}
/*--------------清DDRAM------------------*/
void clrram (void)
{
  WriteCommandLCM(0x30);
  WriteCommandLCM(0x01);
  Delay(180);
}
/*****************************************************/
void img_disp (uchar code *img)
{
  uchar i,j;
  for(j=0;j<32;j++)
  {
    for(i=0;i<8;i++)
    {
      WriteCommandLCM(0x34);
      WriteCommandLCM(y+j);
      WriteCommandLCM(x1+i);
      WriteCommandLCM(0x30);
      WriteDataLCM(img[j*16+i*2]);
      WriteDataLCM(img[j*16+i*2+1]);
    }
  }
  for(j=32;j<64;j++)
  {
    for(i=0;i<8;i++)
    {
      WriteCommandLCM(0x34);
      WriteCommandLCM(y+j-32);
      WriteCommandLCM(x2+i);
      WriteCommandLCM(0x30);
      WriteDataLCM(img[j*16+i*2]);
      WriteDataLCM(img[j*16+i*2+1]);
    }
  }
  WriteCommandLCM(0x36);
}
/*****************************************************/

void main(void)
{
     
   InitSPI();                           //initial SPI
   Delay(10);
   Lcdinit();                           // 初始化LCD
   while(1)
   {
   clrram();
   img_disp(logo);
   Delay(50000);Delay(50000);Delay(50000);Delay(50000);
   clrram();
   chn_disp(tab1);
   Delay(50000);Delay(50000);Delay(50000);Delay(50000);
   }

}

 

 

重新看了下STC12系列单片机的PDF,发现原先的SPI总线初始化程序有问题,即设定了MASTER位之后,仍旧可以通过拉低ss(P1.4)来使主机变为从机。这个问题在PDF中已经考虑到了,需要设置SSIG位为1,这样就可以放心大胆的使用P1.4作为外部器件的片选端了。新的配置程序如下(包含注释):

 

//引脚定义
sbit    LCD_CS    =P1^3;// 片选 高电平有效,可固定为高电平,相当于SPI总线中ss端口,
//注;P1.4为STC的SS端口,如果在SPI初始化代码中未设定模块角色由MASTER位决定,则强行拉低P1.4将导致单片机由主机变为从机。
//数据 LCD_SID   =P1^5;    //SPIMOSI
//时钟 LCD_CLK   =P1^7;    //SPICLK

 

#define MASTER                  //define:master undefine:slave

void InitSPI()
{
    SPDAT = 0;                  //initial SPI data
    SPSTAT = SPIF | WCOL;       //clear SPI status
#ifdef MASTER
    SPCTL = SPEN | MSTR | CPHA | CPOL | SPSPEEDH | SSIG;               //master mode
 //spi使能 主模式 相位选择 下降沿触发 最快速度 主机由master位决定
#else
    SPCTL = SPEN;               //slave mode
#endif
}

抱歉!评论已关闭.