[DemoCode下载] 在新唐(nuvoton)Cortex M0上实现12864液晶屏显示

[复制链接]
 楼主| Roderman_z 发表于 2015-12-12 20:53 | 显示全部楼层 |阅读模式
在经历过3天的不断探索后,本人终于实现了在nuvoton Cortex M0上搭载一个12864的LCD液晶屏。用于显示四行最简单的中文字符串。下面我就把自己的实践过程记录下来,希望能够在此基础上不断提高,最终要能记录M0的控制信息,以实现人机交互的功能。一、硬件配置
配置12864液晶的电路非常简单,市场上的通用12864液晶屏具有20个引脚,其每个引脚的功能说明如下表。


这里有几个要注意的地方:
3脚、16脚、18脚不用管它,悬空;
RS做数据/指令选择位,RS=1表示输入数据,RS=0表示数据指令;
R/W 读写控制位,高电平为读数据,低电平为写数据;
E 使能端,高电平有效
PSB 串/并模式选择 高电平为并行模式,低电平为串行模式
RST 复位位 低电平有效
DB[0..7] 数据位
 楼主| Roderman_z 发表于 2015-12-12 20:54 | 显示全部楼层
下面是液晶接口电路原理图:




P2.0口做RS
P2.1口做R/W
P2.2口做E
P0口的0-7位做数据或指令输入口
P2.3口做PSB
P2.4口不用
P2.5口做复位位RST
另:图上的JPBG是接背光选择的,电阻是用来控制背光大小。

 楼主| Roderman_z 发表于 2015-12-12 20:55 | 显示全部楼层
二、程序设计
要注意的是ARM系列微控制器GPIO口在使用时的问题,特别要注意每次输出0和输出1,使用的都是不同的寄存器。而且,GPIO口的功能每次也都需要设定它是做输入,输出还是做准双向口或者开漏模式。这一点很重要,与单片机不同,所以如果这里编程时序不注意会导致失败。
编程过程中,我使用了符合CMSIS标准的ARM Cortex微控制器标准API函数库来调用GPIO口操作函数,主要用到的有:
(1)DrvGPIO_Open
Prototype
      void DrvGPIO_Open ( E_DRVGPIO_PORT  port, E_DRVGPIO_PIN  pin, E_DRVGPIO_IO  IOMode )                Description
      Set the specified GPIO pin to the specified GPIO operation mode.
Parameter
      port [in]   E_DRVGPIO_PORT, specify GPIO port.   
It could be E_PORT0, E_PORT1, E_PORT2, E_PORT3 and E_PORT4.
      pin [in]
Specify pin of the GPIO port. It could be E_PIN0, E_PIN2 ... ~ E_PIN7.
      IOMode [in]
          E_DRVGPIO_IO, set the specified GPIO pin to be E_IO_INPUT, E_IO_OUTPUT, E_IO_OPENDRAIN or E_IO_QUASI mode.
Include
  Driver/DrvGPIO.h
Return Value
    None
Example:
  1. DrvGPIO_Open (E_PORT0, E_PIN0, E_IO_OUTPUT);
  2.   DrvGPIO_Open (E_PORT0, E_PIN1, E_IO_INPUT);
 楼主| Roderman_z 发表于 2015-12-12 20:57 | 显示全部楼层
(2)DrvGPIO_SetBit
Prototype
      int32_t DrvGPIO_SetBit (E_DRVGPIO_PORT port, E_DRVGPIO_PIN pin)
Description
     Set the specified GPIO pin to 1.
Parameter
      port [in]   
  E_DRVGPIO_PORT, specify GPIO port.   
       It could be E_PORT0, E_PORT1, E_PORT2, E_PORT3 and E_PORT4.
      pin [in]
        Specify pin of the GPIO port. It could be E_PIN0, E_PIN2 ... ~ E_PIN7.
Include
  Driver/DrvGPIO.h
Return Value
  E_SUCCESS:   Operation successful
Example:  
  1. DrvGPIO_Open (E_PORT0, E_PIN0, E_IO_OUTPUT);
  2.    
  3.   DrvGPIO_SetBit (E_PORT0, E_PIN0);
 楼主| Roderman_z 发表于 2015-12-12 20:58 | 显示全部楼层
(3)DrvGPIO_ClrBit
Prototype
      int32_t DrvGPIO_ClrBit (E_DRVGPIO_PORT port, E_DRVGPIO_PIN pin)
Description
  Set the specified GPIO pin to 0.
Parameter     
      port [in]   
  E_DRVGPIO_PORT, specify GPIO port.   
       It could be E_PORT0, E_PORT1, E_PORT2, E_PORT3 and E_PORT4.
      pin [in]
        Specify pin of the GPIO port. It could be E_PIN0, E_PIN2 ... ~ E_PIN7.
Include
  Driver/DrvGPIO.h
Return Value
  E_SUCCESS:            Operation successful
Example:  
  1. DrvGPIO_Open (E_PORT0, E_PIN0, E_IO_OUTPUT);
  2.    
  3.   DrvGPIO_ClrBit (E_PORT0, E_PIN0);
 楼主| Roderman_z 发表于 2015-12-12 20:59 | 显示全部楼层
(4)DrvGPIO_SetPortBits
Prototype
      int32_tDrvGPIO_SetPortBits (E_DRVGPIO_PORT port, int32_t i32PortValue)
Description
      Set the output port value to the specified GPIO port.
Parameter
      port [in]   
    E_DRVGPIO_PORT, specify GPIO port.   
       It could be E_PORT0, E_PORT1, E_PORT2, E_PORT3 and E_PORT4.
  i32PortValue [in]
  The data output value. It could be 0~0xFF.
Include
  Driver/DrvGPIO.h
Return Value
  E_SUCCESS:            Operation successful
Example:
  1. DrvGPIO_SetPortBits (E_PORT0, 0x12);

看到了上面介绍的这些库函数,就可以开始看12864的指令集了,下面把指令集附在后面
 楼主| Roderman_z 发表于 2015-12-12 21:01 | 显示全部楼层
三、程序代码
lcd.c
  1. //延时子程序模块
  2. //**********************************************
  3. void longdelay(uint32_t delay) //长延时程序延时 n*100ms
  4. { uint32_t i;
  5.   for(;delay>0;delay--)
  6.     {for(i=0;i<100;i++) //100ms延时.
  7.         DrvSYS_Delay (1000); //调用库函数,延时n us
  8.     }
  9. }

  10. void shortdelay(uint32_t dly) //短延时程序 nms
  11. {
  12. for(;dly>0;dly--)
  13. DrvSYS_Delay(1000);
  14. }

  15. //**********************************
  16. //液晶初始化
  17. //**********************************
  18. void init_lcd(void)
  19. { uint8_t comm;
  20. shortdelay(3);
  21. comm=0x01; //清除显示
  22. wr_i_lcd(comm);
  23. shortdelay(3);
  24. comm=0x30; //普通指令集格式
  25. wr_i_lcd(comm);
  26. shortdelay(3);
  27. comm=0x06; //光标右移
  28. wr_i_lcd(comm);
  29. shortdelay(3);
  30. comm=0x02; //地址归位
  31. wr_i_lcd(comm);
  32. shortdelay(3);
  33. comm=0x06; //整体不移动
  34. wr_i_lcd(comm);
  35. shortdelay(3);
  36. comm=0x0c; //整体显示,不反白
  37. wr_i_lcd(comm);
  38. shortdelay(3);
  39. comm=0x01; //复位
  40. wr_i_lcd(comm);
  41. shortdelay(3);
  42. comm=0x80; //设定DDRAM起始为0x80
  43. wr_i_lcd(comm);
  44. shortdelay(3);
  45. }
 楼主| Roderman_z 发表于 2015-12-12 21:02 | 显示全部楼层
  1. //***********************************
  2. //填充液晶DDRAM全为空格
  3. //**********************************
  4. void clrram_lcd(void)
  5. { uint16_t data;
  6. data=0x30;
  7. wr_i_lcd(data);
  8. shortdelay(3);
  9. data=0x01;
  10. wr_i_lcd(data);
  11. longdelay(2);
  12. }
  13. //***********************************
  14. //对液晶写数据
  15. //content为要写入的数据
  16. //***********************************
  17. void wr_d_lcd(uint8_t content)
  18. {
  19. busy_lcd();
  20. DrvGPIO_Open(E_PORT2, E_PIN0, E_IO_OUTPUT);
  21. DrvGPIO_Open(E_PORT2, E_PIN1, E_IO_OUTPUT);
  22. DrvGPIO_Open(E_PORT2, E_PIN2, E_IO_OUTPUT);
  23. DrvGPIO_SetBit(E_PORT2, E_PIN0); //rs=1,data mode
  24.     DrvGPIO_ClrBit(E_PORT2, E_PIN1); //rw=0,write mode

  25. DrvGPIO_Open(E_PORT0, E_PIN0, E_IO_OUTPUT);
  26. DrvGPIO_Open(E_PORT0, E_PIN1, E_IO_OUTPUT);
  27. DrvGPIO_Open(E_PORT0, E_PIN2, E_IO_OUTPUT);
  28. DrvGPIO_Open(E_PORT0, E_PIN3, E_IO_OUTPUT);
  29. DrvGPIO_Open(E_PORT0, E_PIN4, E_IO_OUTPUT);
  30. DrvGPIO_Open(E_PORT0, E_PIN5, E_IO_OUTPUT);
  31. DrvGPIO_Open(E_PORT0, E_PIN6, E_IO_OUTPUT);
  32. DrvGPIO_Open(E_PORT0, E_PIN7, E_IO_OUTPUT);

  33. DrvGPIO_SetPortBits(E_PORT0,content); //write data

  34. DrvGPIO_SetBit(E_PORT2, E_PIN2); //enable
  35. shortdelay(2);
  36. DrvGPIO_ClrBit(E_PORT2, E_PIN2); //disable
  37. }
  38. //********************************
  39. //对液晶写指令
  40. //content为要写入的指令代码
  41. //*****************************
  42. void wr_i_lcd(uint8_t content)
  43. {
  44. busy_lcd();
  45. DrvGPIO_Open(E_PORT2, E_PIN0, E_IO_OUTPUT);
  46. DrvGPIO_Open(E_PORT2, E_PIN1, E_IO_OUTPUT);
  47. DrvGPIO_Open(E_PORT2, E_PIN2, E_IO_OUTPUT);
  48. DrvGPIO_ClrBit(E_PORT2, E_PIN0); //rs=0,command mode
  49.     DrvGPIO_ClrBit(E_PORT2, E_PIN1); //rw=0,write mode

  50. DrvGPIO_Open(E_PORT0, E_PIN0, E_IO_OUTPUT);
  51. DrvGPIO_Open(E_PORT0, E_PIN1, E_IO_OUTPUT);
  52. DrvGPIO_Open(E_PORT0, E_PIN2, E_IO_OUTPUT);
  53. DrvGPIO_Open(E_PORT0, E_PIN3, E_IO_OUTPUT);
  54. DrvGPIO_Open(E_PORT0, E_PIN4, E_IO_OUTPUT);
  55. DrvGPIO_Open(E_PORT0, E_PIN5, E_IO_OUTPUT);
  56. DrvGPIO_Open(E_PORT0, E_PIN6, E_IO_OUTPUT);
  57. DrvGPIO_Open(E_PORT0, E_PIN7, E_IO_OUTPUT);

  58. DrvGPIO_SetPortBits(E_PORT0,content); //write command

  59. DrvGPIO_SetBit(E_PORT2, E_PIN2); //enable
  60. shortdelay(2);
  61. DrvGPIO_ClrBit(E_PORT2, E_PIN2); //disable
  62. }
 楼主| Roderman_z 发表于 2015-12-12 21:04 | 显示全部楼层
  1. //********************************
  2. //液晶检测忙状态
  3. //在写入之前必须执行
  4. //********************************
  5. void busy_lcd(void)
  6. {
  7. DrvGPIO_Open(E_PORT0, E_PIN0, E_IO_OUTPUT); //下面几行都为打开P0端口,设定为输出模式
  8. DrvGPIO_Open(E_PORT0, E_PIN1, E_IO_OUTPUT);
  9. DrvGPIO_Open(E_PORT0, E_PIN2, E_IO_OUTPUT);
  10. DrvGPIO_Open(E_PORT0, E_PIN3, E_IO_OUTPUT);
  11. DrvGPIO_Open(E_PORT0, E_PIN4, E_IO_OUTPUT);
  12. DrvGPIO_Open(E_PORT0, E_PIN5, E_IO_OUTPUT);
  13. DrvGPIO_Open(E_PORT0, E_PIN6, E_IO_OUTPUT);
  14. DrvGPIO_Open(E_PORT0, E_PIN7, E_IO_OUTPUT);
  15. DrvGPIO_Open(E_PORT2, E_PIN0, E_IO_OUTPUT);
  16. DrvGPIO_Open(E_PORT2, E_PIN1, E_IO_OUTPUT);
  17. DrvGPIO_Open(E_PORT2, E_PIN2, E_IO_OUTPUT);
  18.   DrvGPIO_SetPortBits(E_PORT0,0xff);
  19.   DrvGPIO_ClrBit(E_PORT2, E_PIN0); //rs=0
  20.   DrvGPIO_SetBit(E_PORT2, E_PIN1); //rw=1,read
  21.   DrvGPIO_SetBit(E_PORT2, E_PIN2); //enable
  22. DrvGPIO_Open(E_PORT0, E_PIN7, E_IO_INPUT); //set p0.7 as a input pin ==busy
  23.   while((DrvGPIO_GetBit (E_PORT0, E_PIN7))!=0); //while is busy
  24.   DrvGPIO_ClrBit(E_PORT2, E_PIN2); //disable
  25. }
  26. //********************************
  27. //指定要显示字符的坐标
  28. //*******************************
  29. void gotoxy(uint8_t y,uint8_t x)
  30. {
  31. if(y==1)
  32. wr_i_lcd(0x80|x); //第一行
  33. if(y==2)
  34.         wr_i_lcd(0x90|x); //第二行
  35. if(y==3)
  36. wr_i_lcd((0x80|x)+8); //第三行
  37. if(y==4)
  38.         wr_i_lcd((0x90|x)+8); //第四行
  39. }
  40. //**********************************
  41. //液晶显示字符串程序
  42. //**********************************
  43. void print(uint8_t *str)
  44. {
  45. while(*str!='\0')
  46. {
  47. wr_d_lcd(*str);
  48. str++;
  49. }
  50. }
 楼主| Roderman_z 发表于 2015-12-12 21:05 | 显示全部楼层
  1. /***************************************
  2. //液晶显示主程序模块
  3. //***************************************
  4. void show()   
  5. {
  6.   
  7.   gotoxy(1,0);
  8.   print("南京航空航天大学");
  9.   shortdelay(200);            
  10.   gotoxy(2,0);
  11.   print("计算机科学与技术");
  12.   shortdelay(200);                 //扫描延时
  13.   gotoxy(3,0);
  14.   print("WWW.NUAA.EDU.CN");
  15.   shortdelay(200);                 //扫描延时
  16.   gotoxy(4,0);
  17.   print("12864 液晶测试");
  18.   shortdelay(200);                 //扫描延时
  19. }
捉虫天师 发表于 2016-1-31 14:25 | 显示全部楼层
:handshake
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

354

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部