ZIGBEE学习之SPI总线方式点亮LCD屏幕

来源:互联网 发布:手机数据恢复精灵 破解 编辑:程序博客网 时间:2024/04/25 22:47

今天的任务是用SPI总线方式点亮LCD屏幕,呵呵这里要涉及到两个内容,一个是SPI总线,一个LCD。


CC2430的话已经集成了SPI总线,只要将IO口配置为外设,然后将USART配置成SPI方式就可以了。


关于LCD其实也很简单,很多没有接触过的同学可能将其想象的太过复杂了,就是将字或者图像转换为一个一个的点,如果要这点显示东西呢,就把这点点亮,否则则不点亮。其实PCD8544已经将很多细节的东西做好了,我们要做的呢,就是发送一串命令序列,然后发送要显示的数据就可以了。看看PCD8544的芯片资料,我们还会发现在最后它竟然给出了操作实例,呵呵相信大家都能看懂的吧,如果有看不懂的可以给我留言或者是QQ联系我哦,我如果知道的话一定给大家详细的答复!


CC2430的SPI的是放在USART外设里面的,和UART放在一起,同一个USART即可以配置成UART也可以配置成SPI,SPI的主从模式通过相关的寄存器来选择。关于管脚的分配也不难,这里就不多说了,其实这里还算是8051的基础实验,对于8051很熟悉的同学肯定觉得我是在说废话了,哈哈!


这里只提一下关于SPI应该注意的一点问题:


1、PCD8544 的SPI是高电平采样,所以,主机端必须是高电平之前要把数据准备好。所以主机端的发送(MOSI)因该设为下降沿采样。
当用SPI和PCD8544通信时,速率不能太低,否则点不亮LCD,或者是出来乱码


下面是引用网友的SPI总线心得,我觉得看看很有益处:


SPI接口时钟配置心得:
   在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,
因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要
搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。
但要注意的是,由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,
从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,
所以主设备这边SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,
跟从设备SDO发送数据的极性是相同的。下面这段话是Sychip Wlan8100 Module Spec上说的,
充分说明了时钟极性是如何配置的:
The 81xx module will always input data bits at the rising edge of the clock,
and the host will always output data bits on the falling edge of the clock.
意思是:主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据。
因此主设备这边SPI时钟极性应该配置为下降沿有效。
又如,下面这段话是摘自LCD Driver IC SSD1289:
SDI is shifted into 8-bit shift register on every rising edge of SCK in the order
of data bit 7, data bit 6 …… data bit 0.
意思是:从设备SSD1289在时钟的上升沿接收数据,而且是按照从高位到地位的顺序接收数据的。
因此主设备的SPI时钟极性同样应该配置为下降沿有效。
   时钟极性和相位配置正确后,数据才能够被准确的发送和接收。
因此应该对照从设备的SPI接口时序或者Spec文档说明来正确配置主设备的时钟。


老规矩,上程序:


先来一个不用SPI方式控制LCD显示的实例:


#include "periodef.h"
#include <string.h>


void delay(uint n){
  //26 cycles delay
  while(--n)asm("NOP");
}


void LCD_IOInit(){
  P0SEL &=~ 0X03;
  P0DIR |=  0X03;
  P1SEL &=~ 0XF0;
  P1DIR |=  0XF0;
}


void LCD_WriteOneByte(uchar data){
   uchar i = 0;
   for(i=0;i<8;i++){
     LCD_SCK = 0;
     if((data<<i)&0x80){
      LCD_SIN = 1;
     }
     else{LCD_SIN = 0;}
     LCD_SCK = 1;
   }
}


void LCD_WriteMByte(uchar *data,uint num){
  while(num--){
    LCD_WriteOneByte(*data);
    data++;
  }
}


void LCD_Init(){
  LCD_nCS  = 0;
  delay(100);
  LCD_nRES = 0;
  delay(100);
  LCD_nRES = 1;
  delay(100);
  LCD_DnC  = 0;
  LCD_WriteOneByte(0x21);
  LCD_WriteOneByte(0xC8);
  LCD_WriteOneByte(0x06);
  LCD_WriteOneByte(0x13);
  LCD_WriteOneByte(0x20);
  LCD_WriteOneByte(0x0C);
  LCD_DnC  = 1;
}


main(){
  uint i = 0;
  uchar Hello[]={
  0x00,0x7E,0x10,0x10,0x7E,0x00,/*"H",0*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x7E,0x52,0x52,0x42,0x00,/*"E",1*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",2*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",3*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x3C,0x42,0x42,0x3C,0x00,/*"O",4*/
  /* (6 X 8 , 楷体_GB2312 )*/};
  LCD_IOInit();
  LCD_Init();
  //for(i=0;i<30;i++){
   //LCD_WriteOneByte(Hello);
  //}
  LCD_WriteMByte(Hello,30);
  LCD_nCS = 1;
}
下面是采用SPI总线方式控制LCD显示的例子:


//========================
//This file is applicable to Eshine EXBEE-DK V1
//Function:LCD test,the LCD use SPI BUS.The SPI BUS occupation P1-USART1-ALT.2
//InPut   :
//OutPut  :
//Created :longfan,2010.1.10
//Modify  :
//========================
#include "periodef.h"
#include "font.h"
#include "TestBMP.h"
#include <string.h>


void delay(uint n){
  //26 cycles delay
  while(--n)asm("NOP");
}


void LEDInit(){
  P1SEL &= 0XFE;        //P1_0 defined General purpose I/O
  P1DIR |= 0X01;        //P1_0 defined Output
  DEBUG_LED = 1;        //LED light up
}
//========================
//Initial P1-USART1-SPI
void SPIInit_U1_P1(void){
  PERCFG |= 0X02;        //USART1.alt.2,P1
  P1SEL  |= 0XE0;        //P1,ISP,P1_4(LCD_DnC) defined general IO
  P2SEL  |= 0X40;        //USART1 has priority


  U1GCR  |= 0x20;        //MSB first,Negative clock polarity,Data is output on MOSI on the falling edge of CLK
  U1GCR  |= 19;          //MAX Baud rate(17),falling edge
  U1BAUD = 0;
  UTX1IF = 0;            //Clear interrupt
}
//========================
//P1-USART1-SPI Send One Byte
void SPI_SendOne_U1_P1(uchar data){
    U1DBUF = data;
    while(!UTX1IF);
    UTX1IF = 0;
}
//========================
//P1-USART1-SPI Send Multily Byte
void SPI_Send_U1_P1(uchar *data,uint length){
  while(length){
    SPI_SendOne_U1_P1(*data);
    data++;
    length -= 1;
  }
}
//========================
//LCD Use SPI BUS,Set the first display piex.
//When after call this function can direct call SPI data output function
//0<X<83,0<Y<5
void SPI_LCDSetPos(uchar X,uchar Y){
  LCD_DnC = 0;
  SPI_SendOne_U1_P1(0x80 | X);
  SPI_SendOne_U1_P1(0x40 | Y);
  LCD_DnC = 1;
}
//========================
//LCD Use SPI BUS,Clear the LCD Display and its RAM.
void SPI_ClearLCD(){
  uint i;
  SPI_LCDSetPos(0,0);
  for (i=0; i<504; i++){
    SPI_SendOne_U1_P1(0);
  }
}
//========================
//LCD Use SPI BUS,Send one LCD Command
void SPI_LCDWriteOneComm(uchar command){
  LCD_DnC = 0;
  SPI_SendOne_U1_P1(command);
}
//========================
//LCD Use SPI BUS,Send More than one LCD Command
void SPI_LCDWriteMulComm(uchar *command,uchar num){
  LCD_DnC = 0;
  SPI_Send_U1_P1(command,num);
}
//========================
//LCD Use SPI BUS,Send More than one data
void SPI_LCDWriteData(uchar *data,uchar length){
  LCD_DnC = 1;
  SPI_Send_U1_P1(data,length);
}
//========================
//LCD Use SPI BUS,Display a english character Without set position,The inverse argument control
//the inverse video mode.When use font library call this function to display.
//InPut   :character:The character want to display
//         inverse  :Inverse video mode(1) or not(0)
//OutPut  :
//Created :longfan,2010.1.10
//Modify  :
//========================
void SPI_LCDWriteChar(uchar character,uchar inverse){
  uchar line;
  LCD_DnC = 1;
  if(inverse){
    for(line=0;line<6;line++){
      SPI_SendOne_U1_P1(~font6x8[character-32][line]);
    }
  }else{
    SPI_Send_U1_P1((uchar *)font6x8[character-32],6);
  }
}
//========================
//LCD Use SPI BUS,Display a english character at (X,Y),The inverse argument control
//the inverse video mode.When use font library call this function to display.
//InPut   :character:The character want to display
//         X,Y      :The position want to display
//         inverse  :Inverse video mode(1) or not(0)
//OutPut  :
//Created :longfan,2010.1.10
//Modify  :
//========================
void SPI_LCDDISPChar(uchar character,uchar X,uchar Y,uchar inverse){
  uchar line;
  SPI_LCDSetPos(X,Y);
  if(inverse){
    for(line=0;line<6;line++){
      SPI_SendOne_U1_P1(~font6x8[character-32][line]);
    }
  }else{
    SPI_Send_U1_P1((uchar *)font6x8[character-32],6);
  }
}
//========================
//LCD Use SPI BUS,Display a english string at (X,Y)
void SPI_LCDWriteEnString(uchar *EnString,uchar X,uchar Y,uchar inverse){
  uchar line;
  SPI_LCDSetPos(X,Y);
  while(*EnString){
    uchar chara = *EnString;
    chara -= 32;
    if(inverse){
      for(line=0;line<6;line++){
        SPI_SendOne_U1_P1(~font6x8[chara][line]);
      }
    }else{
      SPI_Send_U1_P1((uchar *)font6x8[chara],6);
    }
    EnString++;
  }
}
//========================
//LCD Use SPI BUS,Draw a AREA use Horizontal(thus the High pixel must be a multiple of 8).
//When use dot matrix to display use this function.
//InPut   :data     :The dot matrix of the data want to display
//         X,Y      :The position want to display
//         wide,high:The pixel of wide and high
//OutPut  :
//Created :longfan,2010.1.10
//Modify  :
//========================
void SPI_LCDDrawArea_H(uchar *data,uchar X,uchar Y,uchar wide,uchar high){
  uchar row;
  uchar i;
  SPI_LCDSetPos(X,Y);         //Set position
  row = high/8;               //calculate the row number
  for(i=0;i<row;i++){
    SPI_Send_U1_P1(data+(i*wide),wide);
    Y += 1;
    SPI_LCDSetPos(X,Y);       //Set position
  }
}
//========================
//LCD Use SPI BUS,Initial LCD
void SPI_LCDInit(){
  P0DIR  |= 0X03;           //P00(LCD_nCS),P01(LCD_nRES) Defined output
  P1DIR  |= 0X10;           //P1_4(LCD_DnC) defined Outpu
  P2DIR  |=  1;             //LCD_BKL
  LCD_nCS = 0;              //LCD Enable
  delay(100);
  LCD_nRES = 0;             //LCD RESERT
  delay(100);
  LCD_nRES = 1;
  delay(100);
  LCD_BKL = 0;              //D5 light up
  //Send Initial command
  //LCD_DnC = 0;
  //SPI_SendOne_U1_P1(0x21);        //Chip is active,Horizontal addressing,Use extended instruction set
  //SPI_SendOne_U1_P1(0xC8);        //Set Vop
  //SPI_SendOne_U1_P1(0x06);        //Temperature coefficient
  //SPI_SendOne_U1_P1(0x13);        //1:48
  //SPI_SendOne_U1_P1(0x20);        //Use basic instruction set
  //SPI_SendOne_U1_P1(0x0C);        //Display mode is Normal mode
  uchar Init_Comm[]={0x21,0xC8,0x06,0x13,0x20,0X0C};
  SPI_LCDWriteMulComm(Init_Comm,6);
  SPI_ClearLCD();                   //Clear Display RAM
  SPI_LCDWriteOneComm(0X0C);
  LCD_DnC = 1;                      //Send Display Data
}


main(){
  uchar Hello[]={ 
  0x00,0x7E,0x10,0x10,0x7E,0x00,/*"H",0*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x7E,0x52,0x52,0x42,0x00,/*"E",1*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",2*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",3*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x3C,0x42,0x42,0x3C,0x00,/*"O",4*/
  /* (6 X 8 , 楷体_GB2312 )*/


   0x00,0x7E,0x10,0x10,0x7E,0x00,/*"H",0*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x7E,0x52,0x52,0x42,0x00,/*"E",1*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",2*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x42,0x7E,0x42,0x40,0x40,0x00,/*"L",3*/
  /* (6 X 8 , 楷体_GB2312 )*/
  0x00,0x3C,0x42,0x42,0x3C,0x00,/*"O",4*/
  /* (6 X 8 , 楷体_GB2312 )*/};
  uchar *tring = "Hello,CC2430! i LOVE THIS!";
  uchar *tring1= "Hello,CC2430!";
  LEDInit();
  SPIInit_U1_P1();
  SPI_LCDInit();


  //SPI_Send_U1_P1((uchar *)EshineLOGO,sizeof(EshineLOGO)/sizeof(uchar));
  //delay(50000);
  //delay(50000);
  //delay(50000);
  //delay(50000);
  //delay(50000);
  //SPI_ClearLCD();
  //PI_Send_U1_P1(Hello,sizeof(Hello)/sizeof(uchar));
  //SPI_LCDDISPChar('Q',0,0,1);
  //SPI_LCDWriteEnString(tring,10,0,0);
  //SPI_LCDWriteEnString(tring,0,2,1);


  //SPI_LCDDrawArea_H(Hello,40,4,30,16);
  //SPI_ClearLCD();
  //SPI_LCDSetPos(0,0);
  //SPI_Send_U1_P1((uchar *)LOGO,sizeof(LOGO)/sizeof(uchar));
  //SPI_LCDWriteData((uchar *)LOGO,sizeof(LOGO)/8);
  SPI_LCDWriteData((uchar *)LOGO,sizeof(LOGO)/sizeof(uchar));
}
所有程序和配置文件都已经打包上传!

原创粉丝点击