找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5316|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM8L驅(qū)動(dòng)LCD1602液晶屏

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:145459 發(fā)表于 2016-11-1 00:29 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
由于上次諾基亞5110的液晶屏接觸不良,所以沒辦法用在我要做的自平衡小車上面.我主要是想用液晶屏顯示PID參數(shù),用兩個(gè)按鍵設(shè)置PID,方便平衡小車的調(diào)試.
我手中只剩下LCD1602這款液晶屏了,雖然一直很嫌棄它(驅(qū)動(dòng)IO多,顯示字符少)但也沒辦法.
本文使用四線驅(qū)動(dòng)LCD1602的方法,主要是八線驅(qū)動(dòng)太占用IO口.關(guān)于四線驅(qū)動(dòng),網(wǎng)上有很多例程可以參考,我也是參考網(wǎng)上的程序?qū)懙?但在編寫LCD1602驅(qū)動(dòng)程序時(shí),還是經(jīng)歷了很多困難,時(shí)序問題就不提了.網(wǎng)上的很多程序都是沒有判斷忙標(biāo)志位的,直接通過延時(shí)來實(shí)現(xiàn).這樣,延時(shí)時(shí)間多少合適成為一個(gè)問題,我改了好多次延時(shí),但發(fā)現(xiàn)延時(shí)時(shí)間都比較長,寫入一次數(shù)據(jù)的時(shí)間很長.這樣的液晶屏用著很鬧心,刷新一次時(shí)間那么,我的程序還有很多對時(shí)間要求比較苛刻的任務(wù)要執(zhí)行呢,這樣的速度可不行.
關(guān)于四線驅(qū)動(dòng)如何去判斷忙標(biāo)志位,我也不懂,只好去網(wǎng)上搜,很少有這方面的例程,但最后還是找到了一個(gè),照著寫,總算解決了.

上圖是單片機(jī)與LCD1602的接線圖,DB0~DB7為8條并行數(shù)據(jù)線.VL是調(diào)節(jié)液晶屏的對比度的,外接一個(gè)電位器到地,如果顯示不清晰,可以通過此電位器調(diào)節(jié)值最佳對比度.BLK,BLA接液晶背光.
除了8個(gè)數(shù)據(jù)線,和顯示控制有關(guān)的還有RS,RW,E三個(gè)端口,上圖是他們對應(yīng)的功能.

通過向LCD1602寫入命令和數(shù)據(jù)來控制顯示.讀狀態(tài)是為了判斷LCD1602此時(shí)是否處于忙的狀態(tài),如果忙,就只能等待不忙的時(shí)候再進(jìn)行寫操作.通過讀狀態(tài)時(shí)序,讀到一個(gè)八位數(shù)據(jù),最高位是忙標(biāo)志位,此位為1說明此時(shí)忙,為了表示空閑.
大概沒什么要講的了,LCD1602的一些設(shè)置指令比較重要,手上也沒找到詳細(xì)的配置說明.


下圖是LCD1602驅(qū)動(dòng)芯片的顯存,向?qū)?yīng)的顯存地址寫入數(shù)據(jù),就可以控制顯示字符.由于LCD1602自帶了一個(gè)ASCII碼字庫,所以一些常用的字符都可以直接顯示,不需要自己去用軟件生成字庫了.


四線驅(qū)動(dòng)時(shí),寫入的是0x28,八線驅(qū)動(dòng)是寫入的是0x38,如上圖.

四線驅(qū)動(dòng)的寫命令寫數(shù)據(jù)時(shí)序可以參考下面的例程.
本例程,使用STM8L的PB口驅(qū)動(dòng)LCD1602,正好用完P(guān)B口的八個(gè)IO.高四位是數(shù)據(jù)接口,寫入一字節(jié)數(shù)據(jù)時(shí),先寫高四位,再寫第四位.

  1. /*硬件連接*/

  2. //    PB0     -->      RS

  3. //    PB1     -->      RW

  4. //    PB2     -->      E

  5. //    PB3     -->      A(背光正極)

  6. //    PB4     -->      D4

  7. //    PB5     -->      D5

  8. //    PB6     -->      D6

  9. //    PB7     -->      D7

  10. //    PD6     -->      按鍵+

  11. //    PD7     -->      按鍵-



  12. #define   RS_H       PB_ODR_ODR0=1

  13. #define   RS_L       PB_ODR_ODR0=0


  14. #define   RW_H       PB_ODR_ODR1=1

  15. #define   RW_L       PB_ODR_ODR1=0


  16. #define   EN_H       PB_ODR_ODR2=1

  17. #define   EN_L       PB_ODR_ODR2=0


  18. /****************************************************************************************

  19. *開發(fā)環(huán)境:IAR for stm8 v6.5.3

  20. *硬件平臺(tái):STM8L-DISCOVERY

  21. *功能說明:LCD1602四線驅(qū)動(dòng)控制,檢測忙標(biāo)志位    第一行顯示一串字符,第二行顯示一個(gè)可以用按鍵改變大小的三位數(shù)字

  22. *作    者:茗風(fēng)

  23. ****************************************************************************************/

  24. #include"iostm8l152c6.h"

  25. #include"stdbool.h"

  26. #include"stdint.h"

  27. const uint8_t Num_to_Char[10]="0123456789";


  28. /******************************************************************************************************

  29. *  名    稱:void delay_100us(uint8_t x_us)

  30. *  功    能:延時(shí)100us

  31. *  入口參數(shù):無

  32. *  出口參數(shù):無

  33. *  說    明:

  34. *  范    例:無

  35. ******************************************************************************************************/

  36. void delay_100us(uint16_t x_us)

  37. {

  38.   uint8_t j;

  39.   while(x_us--)

  40.   {

  41.     for(j=0;j<33;j++);//2*40個(gè)指令周期

  42.   }

  43.   //delay_10ms共消耗 x_ms*2*255+2*x_ms個(gè)指令周期  

  44.   //*2*40+2*x_ms=80us+

  45.   //16M/8/2=1M 一個(gè)指令周期為1us

  46. }

  47. ///******************************************************************** **********************************

  48. //*  功  能   :LCD1602端口初始化函數(shù)

  49. //*  入口參數(shù) :無

  50. //*  出口參數(shù) :無

  51. //*  說  明   :對LCD1602用的IO端口進(jìn)行初始化

  52. //*  范  例   :無

  53. //******************************************************************************************************/

  54. void LCD1602_GPIO_Init(void)

  55. {

  56.    

  57.   PB_DDR =0xFF;//PB設(shè)置為輸出

  58.   PB_CR1 =0xFF;//PB設(shè)置為推挽輸出

  59.   PB_CR2 =0xFF;//PB的IO輸出速率為10MHz

  60.   PB_ODR =0x00;//PB輸出高電平

  61.   PB_ODR |=0x08;

  62. }

  63. ///******************************************************************************************************

  64. //* 功    能        :LCD1602忙檢測,若不忙則退出,忙則等待

  65. //* 入口參數(shù)        :無

  66. //* 出口參數(shù)        :無

  67. //* 說    明        :

  68. //* 編寫日期  :2016年10月21日

  69. //* 作    者  :茗風(fēng)

  70. //******************************************************************************************************/

  71. void LCD1602_Busy_Check(void)

  72. {

  73.   PB_CR1 &=0x7F;//浮空輸入

  74.   PB_CR2 &=0x7F;//無中斷能力

  75.   PB_DDR &=0x7F;

  76.   PB_ODR |=0x80;

  77.   RS_L;

  78.   RW_H;

  79.   EN_H;

  80.   while(PB_IDR&0x80);

  81.   PB_DDR |=0x80;//PB設(shè)置為輸出

  82.   PB_CR1 |=0x80;//PB設(shè)置為推挽輸出

  83.   PB_CR2 |=0x80;//PB的IO輸出速率為10MHz

  84.   EN_L;

  85. }

  86. ///******************************************************************************************************

  87. //* 功    能        :LCD1602寫命令函數(shù)

  88. //* 入口參數(shù)        :d 寫入的一字節(jié)命令

  89. //* 出口參數(shù)        :無

  90. //* 說    明        :

  91. //* 編寫日期  :2016年10月21日

  92. //* 作    者  :茗風(fēng)

  93. //******************************************************************************************************/

  94. void LCD1602_Write_One_Byte_Cmd(uint8_t d)

  95. {

  96.   LCD1602_Busy_Check();

  97.   

  98.   RW_L;//寫

  99.   RS_L;//命令

  100.        

  101.   PB_ODR &=0x0F;//清高四位

  102.   PB_ODR |=(d&0xF0);

  103.   EN_H;//

  104.   asm("nop");//200ns延時(shí)

  105.   EN_L;

  106.   asm("nop");//200ns延時(shí)

  107.   

  108.   d<<=4;        //低四位移到到高四位

  109.   PB_ODR &=0x0F;//清高四位

  110.   PB_ODR |=(d&0xF0);

  111.   EN_H;

  112.   asm("nop");//200ns延時(shí)

  113.   EN_L;

  114.   asm("nop");//200ns延時(shí)

  115. }

  116. ///******************************************************************************************************

  117. //* 功    能        :LCD1602寫數(shù)據(jù)函數(shù)

  118. //* 入口參數(shù)        :d 寫入的一字節(jié)數(shù)據(jù)

  119. //* 出口參數(shù)        :無

  120. //* 說    明        :

  121. //* 編寫日期  :2016年10月21日

  122. //* 作    者  :茗風(fēng)

  123. //******************************************************************************************************/

  124. void LCD1602_Write_One_Byte_Data(char d)

  125. {

  126.   LCD1602_Busy_Check();

  127.   RS_H;//數(shù)據(jù)

  128.   RW_L;//寫

  129.   

  130.   PB_ODR &=0x0F;//清高四位

  131.   PB_ODR |=(d&0xF0);

  132.   EN_H;

  133.   asm("nop");

  134.   EN_L;

  135. //  asm("nop");

  136. //  delay_100us(1500);

  137.        

  138.   d<<=4;        //低四位移到到高四位

  139.   PB_ODR &=0x0F;//清高四位

  140.   PB_ODR |=(d&0xF0);

  141.   EN_H;

  142.   asm("nop");

  143.   EN_L;

  144.   asm("nop");

  145. //  delay_100us(1500);

  146. }

  147. ///******************************************************************************************************

  148. //* 功    能        :LCD1602一串字符函數(shù)

  149. //* 入口參數(shù)        :x  x軸坐標(biāo),取值范圍(0~15)

  150. //*             y  y軸坐標(biāo),取值范圍(0~1),一共兩行

  151. //*             *s 一串字符

  152. //* 出口參數(shù)        :無

  153. //* 說    明        :

  154. //* 編寫日期  :2016年10月21日

  155. //* 作    者  :茗風(fēng)

  156. //******************************************************************************************************/

  157. uint8_t LCD1602_Display_String(uint8_t x,uint8_t y,uint8_t *s)

  158. {


  159.     if(y==1)

  160.     {

  161.       LCD1602_Write_One_Byte_Cmd(0xC0+x);//設(shè)置寫入字符開始坐標(biāo)  

  162.     }

  163.     else

  164.     {

  165.       LCD1602_Write_One_Byte_Cmd(0x80+x);//設(shè)置寫入字符開始坐標(biāo)  

  166.     }

  167.     while(*s != '\0')

  168.     {

  169.       LCD1602_Write_One_Byte_Data(*s++);

  170.     }

  171.     return 0;

  172. }

  173. ///******************************************************************************************************

  174. //* 功    能        :LCD1602顯示兩位數(shù)字

  175. //* 入口參數(shù)        :x  x軸坐標(biāo),取值范圍(0~15)

  176. //*             y  y軸坐標(biāo),取值范圍(0~1),一共兩行

  177. //*             *s 一串字符

  178. //* 出口參數(shù)        :無

  179. //* 說    明        :

  180. //* 編寫日期  :2016年10月22日

  181. //* 作    者  :茗風(fēng)

  182. //******************************************************************************************************/

  183. void LCD1602_Display_Number(uint8_t x,uint8_t y,uint8_t number)

  184. {


  185.   if(y==1)

  186.   {

  187.     LCD1602_Write_One_Byte_Cmd(0xC0+x);//設(shè)置寫入字符開始坐標(biāo)  

  188.   }

  189.   else

  190.   {

  191.     LCD1602_Write_One_Byte_Cmd(0x80+x);//設(shè)置寫入字符開始坐標(biāo)  

  192.   }

  193.   if(number<10)

  194.   {

  195.      LCD1602_Write_One_Byte_Data(' ');

  196.      LCD1602_Write_One_Byte_Data(' ');

  197.      LCD1602_Write_One_Byte_Data(Num_to_Char[number%10]);

  198.   }

  199.   else if(number<100)

  200.   {

  201.      LCD1602_Write_One_Byte_Data(' ');

  202.      LCD1602_Write_One_Byte_Data(Num_to_Char[number/10]);

  203.      LCD1602_Write_One_Byte_Data(Num_to_Char[number%10]);

  204.   }

  205.   else

  206.   {

  207.      LCD1602_Write_One_Byte_Data(Num_to_Char[number/100]);

  208.      LCD1602_Write_One_Byte_Data(Num_to_Char[number%100/10]);

  209.      LCD1602_Write_One_Byte_Data(Num_to_Char[number%10]);

  210.   }

  211.   

  212. }

  213. ///******************************************************************************************************

  214. //* 功    能        :LCD1602初始化配置

  215. //* 入口參數(shù)        :無

  216. //* 出口參數(shù)        :無

  217. //* 說    明        :

  218. //* 編寫日期  :2016年10月21日

  219. //* 作    者  :茗風(fēng)

  220. //******************************************************************************************************/

  221. void LCD1602_init(void)

  222. {

  223.   LCD1602_GPIO_Init();

  224.   LCD1602_Write_One_Byte_Cmd(0x28);//四線驅(qū)動(dòng)

  225.   LCD1602_Write_One_Byte_Cmd(0x01);//清屏

  226.         LCD1602_Write_One_Byte_Cmd(0x06);//這個(gè)是上面指令碼是 000001NS的設(shè)

  227.   LCD1602_Write_One_Byte_Cmd(0x0C);//顯示開及光標(biāo)設(shè)置

  228. }

  229. ///******************************************************************************************************

  230. //* 功    能        :按鍵GPIO初始化配置

  231. //* 入口參數(shù)        :無

  232. //* 出口參數(shù)        :無

  233. //* 說    明        :

  234. //* 編寫日期    :2016年10月21日

  235. //* 作    者    :茗風(fēng)

  236. //******************************************************************************************************/

  237. void GPIO_Config(void)

  238. {

  239.   //PE7 LED控制引腳

  240.   PE_DDR_DDR7 =1;//輸出

  241.   PE_CR1_C17 =1;//推挽輸出

  242.   PE_CR2_C27 =1;//輸出速率10M

  243.   

  244.   //配置閥門到位檢測引腳PD6,PD7

  245.   PD_DDR_DDR6 =0;

  246.   PD_CR1_C16 =1;//帶上拉電阻輸入

  247.   PD_CR2_C26 =1;//使能外部中斷

  248.   

  249.   PD_DDR_DDR7 =0;

  250.   PD_CR1_C17 =1;//帶上拉電阻輸入

  251.   PD_CR2_C27 =1;//使能外部中斷

  252.   

  253.   EXTI_CR3_PDIS =2;//PD口上升沿中斷

  254. /*00: Falling edge and low level

  255.   01: Rising edge only

  256.   10: Falling edge only

  257.   11: Rising and falling edge*/  

  258.   EXTI_CONF_PDHIS =1;//PD[7:4] are used for EXTID interrupt generation

  259.   

  260. //設(shè)置中斷

  261. //CPU_CCR |=MASK_CPU_CCR_I1+MASK_CPU_CCR_I0;//啟用硬件優(yōu)先級,禁用軟件優(yōu)先級

  262. }

  263. uint8_t num=30;

  264. void main(void)

  265. {

  266.   GPIO_Config();

  267.   LCD1602_init();

  268.   LCD1602_Display_String(0,0,"nannan wo ai ni!");

  269.   LCD1602_Display_String(0,1,"NUM:");

  270.   asm("rim");               //enable interrupts

  271.   while(1)

  272.   {

  273.     LCD1602_Display_Number(4,1,num);

  274.     PE_ODR ^=0x80;

  275.     asm("wfi");

  276.     //delay_100us(10000);

  277.   }

  278. }


  279. #pragma vector=EXTID_vector

  280. __interrupt void EXTID_ISR(void)

  281. {

  282.   delay_100us(100);//10ms延時(shí),暫時(shí)這么做

  283.   if(PD_IDR_IDR6==0)//加

  284.   {

  285.     if(num>256)

  286.       num=255;

  287.     else

  288.       num++;

  289.   }

  290.   else if(PD_IDR_IDR7==0)//減

  291.   {

  292.     if(num==0)

  293.       num=0;

  294.     else

  295.       num--;

  296.   }

  297.   EXTI_SR2_PDF =1;//They are cleared by writing a ‘1’ by software

  298. }
復(fù)制代碼




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表