回答

收藏

【赚周年币】技术帖Week2-Day7——LPC824 Breakout之14、SPI NOKIA5110

#线上活动 #线上活动 3618 人阅读 | 0 人回复 | 2017-01-14

本帖最后由 toofree 于 2017-1-19 03:21 编辑

        【赚周年币】技术帖Week2-Day7——LPC824 Breakout之14、SPI NOKIA5110

        本打算在完成SPI测试之后,就改造一下 NOKIA5110 LCD成硬件SPI接口,但是很不幸,失败了。苦于一直没有找到解决办法,而发愁。在测试了“【赚周年币】技术帖Week2-Day3——LPC824 Lite之十、SPI FLASH测试”之后,找到点感觉,今晚测试终获成功。

        下面我们以之前贴子,“【赚周年币】技术帖Week2-Day1——LPC824 Breakout之八、SPI测试”之后打包上传程序为模板,进行本实验。贴子地址。【赚周年币】技术帖Week2-Day1——LPC824 Breakout之八、SPI测试https://www.cirmall.com/bbs/forum.php?mod=viewthread&tid=62824&fromuid=17147
        


        复制工程“Example_SPI0M_SPI1S”工程文件和源代码文件,改名为“Example_SPI0M_LCD5110”。并且复制之前的“\user_bsp\src\nokia5110.c”和“\user_bsp\inc\nokia5110.h”,改名为“SPI_nokia5110.c” 、“SPI_nokia5110.h” 。修改后的工程如下图。
        


        并对“SPI_nokia5110.c” 、“SPI_nokia5110.h”两个文件做适当修改。
        “SPI_nokia5110.c” 文件58行之前内容有更改后如下:
  1. //#include <Arduino.h>
  2. #include "SPI_nokia5110.h"
  3. #include "ascii.h"
  4. #include "disp_code.h"

  5. volatile unsigned int TCount0 = 0;              //定时计数器0
  6. volatile unsigned int TCount1 = 0;              //定时计数器1
  7. volatile unsigned int TCount2 = 0;              //定时计数器2
  8. //volatile bool Second_Flag = FALSE;           //一秒时间到标志位
  9. //volatile bool Base_Flag = FALSE;             //基准海拔采集标志位
  10. //volatile bool Read_Flag = FALSE;             //读数据时间到标志位
  11. volatile unsigned char Second_Flag = FALSE;           //一秒时间到标志位
  12. volatile unsigned char Base_Flag = FALSE;             //基准海拔采集标志位
  13. volatile unsigned char Read_Flag = FALSE;             //读数据时间到标志位

  14. /*********************************************************************************************************
  15. ** 函数名称: SendRecv_Byte
  16. ** 函数功能:一次传输内部的单字节帧发送与接收
  17. ** 输入参数: 数据线上发送出的数据
  18. ** 输出参数: 数据线上接收到的数据
  19. ** 返 回 值:无
  20. *********************************************************************************************************/
  21. uint8_t Send_Byte (uint8_t ucData)
  22. {
  23.     while (!(LPC_SPI0->STAT & STAT_TXRDY));                               /* 等待发送准备就绪             */
  24.     LPC_SPI0->TXDATCTL = TXDATCTL_FSIZE(7) | TXDATCTL_EOF | ucData;       /* 8 位,帧结束                 */   
  25.    
  26.     while (!(LPC_SPI0->STAT & STAT_RXRDY));                               /* 等待接收数据完成             */
  27.     ucData = LPC_SPI0->RXDAT;                                                   /* 接收数据                     */
  28.    
  29.     return ucData;
  30. }

  31. //发送一字节数据,显示内容的话,一列8位对应一字节,上面对应字节低位
  32. static void SPI_SendByte (uint8_t dat)
  33. {
  34.   uint8_t i;
  35.   
  36.   /*
  37.   for (i = 0; i < 8; i ++)
  38.   {
  39.     NOKIA5110_clk_clear();
  40.     if (dat & 0x80)
  41.     {
  42.       NOKIA5110_din_set();
  43.     }
  44.     else
  45.     {
  46.       NOKIA5110_din_clear();
  47.     }
  48.     dat = dat << 1;
  49.     NOKIA5110_clk_set();
  50.   }
  51.   */

  52.         Send_Byte (dat);

  53. }
复制代码
Home_Init()函数,把SPI接口初始化内容加上,更改后为下:
  1. void Home_Init()
  2. {
  3.   //Serial.begin(9600);                           //串口定义波特率函数

  4.   GPIOSetDir(PORT0, LCD_RST, 1);
  5.   GPIOSetDir(PORT0, LCD_DC, 1);
  6. //  GPIOSetDir(PORT0, LCD_CS, 1);
  7. //  GPIOSetDir(PORT0, LCD_DIN, 1);
  8. //  GPIOSetDir(PORT0, LCD_CLK, 1);
  9.         
  10. // SWM settings for SPI0 (master):
  11. // P0.24 = SPI0_SCK  (requires external connection with P0.28)
  12. // P0.25 = SPI0_MISO (requires external connection with P0.19)
  13. // P0.26 = SPI0_MOSI (requires external connection with P0.4)
  14. // P0.15 = SPI0_SSEL (requires external connection with P0.0)

  15.   // Enable clocks to SPI0/1, SWM (see lpc8xx_syscon.h)
  16.   LPC_SYSCON->SYSAHBCLKCTRL |= (SPI0 | SWM);

  17.   // Configure the SWM (see utilities_lib and lpc8xx_swm.h)
  18.         ConfigSWM(SPI0_SSEL0, P0_24);
  19.         ConfigSWM(SPI0_MOSI, P0_27);
  20.   ConfigSWM(SPI0_SCK, P0_28);
  21.   //ConfigSWM(SPI0_MISO, P0_21);  

  22.   // Configure SPI0 as master, SPI1 as slave
  23.   // Bit rate = 15  m.b.p.s
  24.   // SPI mode 0 (CPOL = 0 CPHA = 0)
  25.   // 8 data bits
  26.   //

  27.   // Setup the SPIs ...
  28.   // Give both SPIs a reset  (see lpc8xx_syscon.h)
  29.   LPC_SYSCON->PRESETCTRL &= (SPI0_RST_N);
  30.   LPC_SYSCON->PRESETCTRL |= ~(SPI0_RST_N);

  31.   // Configure the SPI master's clock divider, slave's value meaningless. (value written to DIV divides by value+1)
  32.   // SCK = SPI_PCLK divided by 2
  33.   LPC_SPI0->DIV = (2-1);

  34.   // Configure the CFG registers:
  35.   // Enable=true, master, no LSB first, CPHA=0, CPOL=0, no loop-back, SSEL active low
  36.   LPC_SPI0->CFG = CFG_ENABLE | CFG_MASTER;
  37.         // Enable=true, master, no LSB first, CPHA=1, CPOL=1, no loop-back, SSEL active low
  38.   //LPC_SPI0->CFG = CFG_ENABLE | CFG_MASTER | CFG_CPHA | CFG_CPOL;

  39.   // Configure the master SPI delay register (DLY), slave's value meaningless.
  40.   // Pre-delay = 0 clocks, post-delay = 0 clocks, frame-delay = 0 clocks, transfer-delay = 0 clocks
  41.   //LPC_SPI0->DLY = 0x0000;
  42.         // Pre-delay = 0 clocks, post-delay = 0 clocks, frame-delay = 0 clocks, transfer-delay = 0 clocks
  43.   LPC_SPI0->DLY = 0;        //0x2222;

  44.   // Configure the SPI control registers
  45.   // Master: End-of-frame true, LEN = 8 bits. Slave: LEN = 8 bits
  46.   LPC_SPI0->TXCTL = CTL_EOF | CTL_LEN(8);
  47.         
  48. }
复制代码
SPI_nokia5110.h”文件62行之前内容更改后如下:
  1. //#include <avr/pgmspace.h>
  2. #include <stdint.h>
  3. #include "lpc8xx_gpio.h"
  4. #include "lpc8xx_syscon.h"

  5. #include "lpc8xx_spi.h"
  6. #include "lpc8xx_swm.h"
  7. #include "utilities.h"

  8. #ifndef TRUE
  9.         #define TRUE                  1
  10. #endif

  11. #ifndef FALSE
  12.         #define FALSE                 0
  13. #endif

  14. #ifndef HIGH
  15.         #define HIGH                  1
  16. #endif

  17. #ifndef LOW
  18.         #define LOW                 0
  19. #endif

  20. extern volatile unsigned int TCount0;              //定时计数器0
  21. extern volatile unsigned int TCount1;              //定时计数器1
  22. extern volatile unsigned int TCount2;              //定时计数器2
  23. //volatile bool Second_Flag = FALSE;           //一秒时间到标志位
  24. //volatile bool Base_Flag = FALSE;             //基准海拔采集标志位
  25. //volatile bool Read_Flag = FALSE;             //读数据时间到标志位
  26. extern volatile unsigned char Second_Flag;           //一秒时间到标志位
  27. extern volatile unsigned char Base_Flag;             //基准海拔采集标志位
  28. extern volatile unsigned char Read_Flag;             //读数据时间到标志位

  29. #define PORT0                        0

  30. /*************************** HAL define ***************************/
  31. //#define   LCD_CS           24
  32. #define   LCD_RST   25
  33. #define   LCD_DC    26
  34. //#define   LCD_DIN   27
  35. //#define   LCD_CLK   28

  36. #define NOKIA5110_CMD                   0
  37. #define NOKIA5110_DATA                  1
  38.                  
  39. #define LCD5110_WIDTH                   84
  40. #define LCD5110_HEIGHT                  5

  41. #define NOKIA5110_reset_clear() GPIOSetBitValue(PORT0, LCD_RST, LOW)  //
  42. #define NOKIA5110_reset_set()   GPIOSetBitValue(PORT0, LCD_RST, HIGH)

  43. #define NOKIA5110_sel_data()    GPIOSetBitValue(PORT0, LCD_DC, HIGH)  //
  44. #define NOKIA5110_sel_cmd()     GPIOSetBitValue(PORT0, LCD_DC, LOW)  //

  45. //#define NOKIA5110_cs_set()      GPIOSetBitValue(PORT0, LCD_CS, HIGH)  //
  46. //#define NOKIA5110_cs_clear()    GPIOSetBitValue(PORT0, LCD_CS, LOW)  //
  47. //#define NOKIA5110_din_set()     GPIOSetBitValue(PORT0, LCD_DIN, HIGH)  //
  48. //#define NOKIA5110_din_clear()   GPIOSetBitValue(PORT0, LCD_DIN, LOW)  //
  49. //#define NOKIA5110_clk_set()     GPIOSetBitValue(PORT0, LCD_CLK, HIGH)  //
  50. //#define NOKIA5110_clk_clear()   GPIOSetBitValue(PORT0, LCD_CLK, LOW)  //
复制代码
之前为什么不行呢,有几个细节没有注意到,看手册不够仔细,被库函数参数误导了。后来参考了,“LPC824 Lite之十、SPI FLASH测试”程序中"w25x32.c"程序中参数,并结合LPC824用户手册205到227页相关内容,终于成功。
        NOKIA5110 LCD的控制器PCD8544数据手册中,SPI时序如下图:
        


        库函数“lpc8xx_spi.c”文件中,TXDATCTL相关位宏定义如下:
      


        而"w25x32.c"文件中的,宏定义有所不同,见下图:
        


       可以看到,一个是(n-1),一个是(s),到底谁是对的呢,现在知道肯定其它一个是错的。为了寻根究底,我们看看数据手册“UM10800.pdf”又是怎么解释的呢。
      
UM10800.pdf (3.2 MB, 下载次数: 16)


         有图有真相。
        

        瞧见没,位27到24的解释,0的话是传输数据长度是1位,1的话2位,依此累推……。于是可以判断"w25x32.c"文件中是正确的,那么我们就依据"w25x32.c"内容来修改发送函数“Send_Byte ()”。宏定义我们不打算用"w25x32.c"文件中的,而使用“lpc8xx_spi.c”文件中的,因为初始化SPI总线时用到的其它函数或宏也都是“lpc8xx_spi.c”文件中的,为了统一。
        
      于是就有了字节发送函数为:
  1. /*********************************************************************************************************
  2. ** 函数名称: SendRecv_Byte
  3. ** 函数功能:一次传输内部的单字节帧发送与接收
  4. ** 输入参数: 数据线上发送出的数据
  5. ** 输出参数: 数据线上接收到的数据
  6. ** 返 回 值:无
  7. *********************************************************************************************************/
  8. uint8_t Send_Byte (uint8_t ucData)
  9. {
  10.     while (!(LPC_SPI0->STAT & STAT_TXRDY));                               /* 等待发送准备就绪             */
  11.     LPC_SPI0->TXDATCTL = TXDATCTL_FSIZE(7) | TXDATCTL_EOF | ucData;       /* 8 位,帧结束                 */   
  12.    
  13.     while (!(LPC_SPI0->STAT & STAT_RXRDY));                               /* 等待接收数据完成             */
  14.     ucData = LPC_SPI0->RXDAT;                                                   /* 接收数据                     */
  15.    
  16.     return ucData;
  17. }
复制代码
“Example_SPI0M_LCD5110.c”文件中主函数main()修改如下:
  1. int main(void) {
  2.   uint32_t temp, n;

  3.   // Configure the debug uart (see Serial.c)
  4.   setup_debug_uart();
  5.         
  6.         // Reset the GPIO module and enable its clock. See peripherals_lib
  7.   GPIOInit();

  8.         printf("Hello world! \r\n");
  9.         
  10.         Home_Init();
  11.         
  12.         NOKIA5110_init();
  13.   NOKIA5110_clear_screen();
  14.         
  15.         NOKIA5110_display_1608_text (0, 0, "LPC824");
  16.         NOKIA5110_display_8x6_text (54, 1, "Board");
  17.         
  18.         NOKIA5110_display_1616_hanzi(1,2,0);
  19.         NOKIA5110_display_1616_hanzi(3,2,1);
  20.         NOKIA5110_display_1616_hanzi(5,2,2);
  21.         NOKIA5110_display_1616_hanzi(7,2,3);
  22.         
  23.         NOKIA5110_display_8x6_text (0, 5, "SPI0 LCD5110");
  24.         
  25.         printf("************************! \r\n");
  26.         
  27.         while (1) {

  28.     GetConsoleString(thestring);                   // See utilities_lib
  29.     printf("Characters to be transmitted (terminated by NUL) are: %s\r\n", thestring);

  30.   } // end of while 1

  31.   //return 0 ;
  32. } // end of main
复制代码
OK,一切就绪,编译、下载程序。LCD显示内容。
        


        依照惯例, 修改后工程文件打包附上。
        
LPC824_Example_Code_Bundle_Keil_r1.0(201701142326).rar (2.83 MB, 下载次数: 30)
关注下面的标签,发现更多相似文章

评分

参与人数 2 +99 收起 理由
EEboard爱板网 + 84 3周发帖养成记 奖励
loveeeboard + 15

查看全部评分

分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条