[DemoCode下载] 新唐M051与LCD1602

[复制链接]
1351|14
 楼主| dongnanxibei 发表于 2016-10-31 23:10 | 显示全部楼层 |阅读模式
根据原来用51单片机写LCD160的经验今天用M051的程序重新整理了一遍,并把8位总线和4位总线的的程序整合到一起。从吃完晚饭就坐这,现在都11点多了,整整搞了一个晚上,废话不多说了,抓紧写完睡觉。
1602采用标准的16脚接口,其中:第1脚:VSS为电源地
第2脚:VCC接5V电源正极
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,使用时可以通过一个10K的电位器调整对比度。我用的这款LCD直接接地,对比度是最佳的,省了不少事。
第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。
第6脚:E(或EN)端为使能端。
第7~14脚:D0~D7为8位双向数据端。
第15脚:背光正极。
第16脚:背光负极。

下图是LCD1602跟M0516的连接图。4总线的D0-D3悬空,D4-D7分别接一个IO的高4位也就是第4-第7位。M0516的这个IO的低4位还可以正常作为其他用途,这样就省了4个IO口。

5321954194892.jpg

下面是接8位总线的实物图及显示效果图。

5321964131928.jpg

下面是接4位总线的实物图及显示效果图。
5321964132036.jpg
 楼主| dongnanxibei 发表于 2016-10-31 23:10 | 显示全部楼层
  1. #include <M051Series.h>
  2. #define PLLCON_SETTING      SYSCLK_PLLCON_50MHz_XTAL
  3. #define PLL_CLOCK           50000000

  4. //#define LCD1602_BUS_NUM 8   //8位数据总线,DB0-DB7 按顺序接到一个IO口的 0-7位
  5. //4位总线,DB4 - DB7 按顺序接到一个IO口的 4-7位,液晶上的DB0-DB3空着,IO口上的0-3位可以正常作为其他用途
  6. #define LCD1602_BUS_NUM 4
  7. #define    LCD1602_DATA_PORT        P1->DOUT            // LCD1602的数据总线
  8. #define LCD1602_RS    P30               // LCD1602的RS
  9. #define LCD1602_RW    P31               // LCD1602的RW
  10. #define LCD1602_E     P32               // LCD1602的E控制线
  11. #define LCD1602_Busy  P17                   // 定义LCD1602的测忙线,应该是LCD1602_DB0_DB7的第8位IO口

  12. void SYS_Init(void)
  13. {
  14. /*---------------------------------------------------------------------------------------------------------*/
  15. /* Init System Clock                                                                                       */
  16. /*---------------------------------------------------------------------------------------------------------*/
  17.     /* Unlock protected registers */
  18.     SYS_UnlockReg();
  19.     /* Enable External XTAL (4~24 MHz) */
  20.     SYSCLK->PWRCON |= SYSCLK_PWRCON_XTL12M_EN_Msk;
  21.     /* Waiting for 12MHz clock ready */
  22.     SYS_WaitingForClockReady( SYSCLK_CLKSTATUS_XTL12M_STB_Msk);
  23.     /* Switch HCLK clock source to XTAL */
  24.     SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_XTAL;

  25.     /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
  26.     SYSCLK->PLLCON|= SYSCLK_PLLCON_PD_Msk;
  27.     /* Set PLL frequency */        
  28.     SYSCLK->PLLCON = PLLCON_SETTING;

  29.     /* Waiting for clock ready */
  30.     SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);

  31.     /* Switch HCLK clock source to PLL */
  32.     SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_PLL;

  33.     /* Enable IP clock */        
  34.     SYSCLK->APBCLK = SYSCLK_APBCLK_PWM01_EN_Msk;
  35.     /* IP clock source */
  36.     SYSCLK->CLKSEL1 = SYSCLK_CLKSEL1_PWM01_XTAL;


  37.     /* Reset PWMB channel0~channel3 */                    
  38.     SYS->IPRSTC2 = SYS_IPRSTC2_PWM47_RST_Msk;                    
  39.     SYS->IPRSTC2 = 0;      




  40.     /* Update System Core Clock */
  41.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  42.     //SystemCoreClockUpdate();
  43.     PllClock        = PLL_CLOCK;            // PLL
  44.     SystemCoreClock = PLL_CLOCK / 1;        // HCLK
  45.     CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

  46. /*---------------------------------------------------------------------------------------------------------*/
  47. /* Init I/O Multi-function                                                                                 */
  48. /*---------------------------------------------------------------------------------------------------------*/
  49.     /* P2.0 for PWM0 */
  50.     //P2.0接LCD1602的背光
  51.     SYS->P2_MFP = SYS_MFP_P20_PWM0 ;
  52.     /* Lock protected registers */
  53.     SYS_LockReg();

  54. }

  55. void PWMA_Init(void)

  56. {
  57.     PWMA->PPR = PWM_PPR_CP01(30) ;
  58.     PWMA->CSR = PWM_CSR_CSR0(PWM_CSR_DIV16);
  59.     //P2.0接LCD1602的背光,可以用PWM进行调光。
  60.     /* Enable PWM0 counter. We must set PWM mode before setting CNR, CMR. */
  61.     PWMA->PCR = PWM_PCR_CH0EN_Msk | PWM_PCR_CH0MOD_AUTO_RELOAD;
  62.     /* PWM0 = 12000000 / 30 / 16 / 200 =    125Hz */
  63.         PWMA->CNR0= 200;
  64.     PWMA->CMR0= 180;

  65.     /* Enable PWM channle 0 Output */
  66.     PWMA->POE = PWM_POE_PWM0_Msk;
  67. }

  68. //********************************************************************************************
  69. // 读LCD忙程序 [底层协议] // (所有底层协议都无需关注)
  70. // LCD1602测忙,若LCD1602处于忙状态,本函数将等待至非忙状态
  71. //********************************************************************************************/
  72. void LCD1602_TestBusy(void){
  73.     LCD1602_DATA_PORT = 0xff;       //设备读状态
  74.     SYS_SysTickDelay(5);
  75.     LCD1602_RS = 0;
  76.     SYS_SysTickDelay(5);
  77.     LCD1602_RW = 1;
  78.     SYS_SysTickDelay(5);
  79.     LCD1602_E = 1;
  80.     while(LCD1602_Busy);        //等待LCD不忙
  81.     LCD1602_E = 0;              //
  82. }
  83. //向LCD1602写入一个指令或者数据
  84. //R_S 1是数据  0是命令
  85. void LCD1602_WriteByte(uint8_t R_S, uint8_t byte)
  86. {
  87.       LCD1602_TestBusy();
  88.         LCD1602_RS = R_S;
  89.         LCD1602_RW = 0;
  90.         #if (LCD1602_BUS_NUM == 8)  //8位总线
  91.             LCD1602_DATA_PORT = byte;
  92.             SYS_SysTickDelay(10);
  93.             LCD1602_E = 1;
  94.             SYS_SysTickDelay(10);
  95.             LCD1602_E = 0;
  96.         #elif (LCD1602_BUS_NUM == 4) //4位总线
  97.             LCD1602_DATA_PORT &= 0x0f; //高四位清0
  98.             LCD1602_DATA_PORT |= (byte&0xf0);//送入高四位数据
  99.             SYS_SysTickDelay(5);
  100.             LCD1602_E = 1;
  101.             SYS_SysTickDelay(5);
  102.             LCD1602_E = 0;      

  103.             LCD1602_DATA_PORT &= 0x0f; //高四位清0
  104.             LCD1602_DATA_PORT|=(byte<<4&0xf0);//送入低四位数据
  105.             SYS_SysTickDelay(5);
  106.             LCD1602_E = 1;
  107.             SYS_SysTickDelay(5);
  108.             LCD1602_E = 0;      
  109.         #endif
  110. }
  111. //********************************************************************************************
  112. // 写指令程序 //
  113. // 向LCD1602写命令 本函数需要1个指令集的入口参数 //
  114. //********************************************************************************************/
  115. void LCD1602_WriteCMD(uint8_t LCD1602_command) {
  116.     LCD1602_WriteByte(0x00,LCD1602_command);
  117. }
  118. //********************************************************************************************
  119. // 写数据程序 //
  120. // 向LCD写数据 //
  121. //********************************************************************************************/
  122. void LCD1602_WriteData(uint8_t LCD1602_data){
  123.     LCD1602_WriteByte(0x01,LCD1602_data);
  124. }
  125. //设置光标位置,line表示第几行,row表示第几列
  126. void LCD1602_SetXY(uint8_t line,uint8_t row)
  127. {
  128.     uint8_t addr;
  129.     if(line>2 || line ==0) line = 1;
  130.     if(row>40 || row == 0) row = 1;
  131.     row +=0x80;
  132.     if(line == 1)
  133.         addr = row - 1;       //第一行
  134.     else if(line == 2)
  135.         addr = row - 1 + 0x40; //第二行
  136.     LCD1602_WriteCMD(addr);
  137. }
  138. //********************************************************************************************
  139. // 打印字符串程序 // (本函数调用指针函数)
  140. //在第x行 第y列 开始显示字符串
  141. //字符串最长48个
  142. //********************************************************************************************/
  143. void LCD1602_PrintString(uint8_t x,uint8_t y,char *str){
  144.     LCD1602_SetXY(x,y);
  145.     while(*str != 0){
  146.         LCD1602_WriteData(*str++);
  147.     }
  148. }
  149. //********************************************************************************************
  150. // 打印单字符程序 //
  151. //在第x行 第y列 显示字符
  152. //* *******************************************************************************************/
  153. void LCD1602_PrintChar(uint8_t x,uint8_t y,char t){
  154.         LCD1602_SetXY(x,y);
  155.         LCD1602_WriteData(t);
  156. }
  157. //********************************************************************************************
  158. // LCD初始化 //(使用者可自定义,加 * 号程序行必须保留但可修改)
  159. //********************************************************************************************/
  160. void LCD1602_Init(void){
  161.     #if (LCD1602_BUS_NUM == 8) //8位总线
  162.         LCD1602_WriteCMD(0x38); // 8总线,显示2行,每个字符为5*7个像素
  163.     #elif (LCD1602_BUS_NUM == 4) //4位总线
  164.         LCD1602_WriteCMD(0x28); // 4总线,显示2行,每个字符为5*7个像素
  165.         //需要设置两次
  166.         LCD1602_WriteCMD(0x28); // 4总线,显示2行,每个字符为5*7个像素
  167.     #endif      
  168.     LCD1602_WriteCMD(0x01); //  显示清屏
  169.     LCD1602_WriteCMD(0x02);     // 数据指针指向第1行第1个字符位置
  170.     LCD1602_WriteCMD(0x06);     //  显示光标移动设置:文字不动,光标右移
  171.     LCD1602_WriteCMD(0x0c);     //  显示开及光标设置:显示开,光标开,闪烁开
  172. }
  173. int main(void)
  174. {
  175.     SYS_Init();
  176.     PWMA_Init();
  177.     LCD1602_Init();
  178.     LCD1602_PrintString(1,3,"QQ:48469646");
  179.     LCD1602_PrintString(2,1,"BUS:4");
  180.     LCD1602_PrintChar(2,7,'O');
  181.     LCD1602_PrintChar(2,8,'K');
  182.     LCD1602_PrintChar(2,9,33);   //叹号
  183.     while(1)
  184.     {
  185.     }
  186. }


mintspring 发表于 2016-11-1 22:09 | 显示全部楼层
用P1的8个端口作为并口发送数据给液晶屏。
 楼主| dongnanxibei 发表于 2016-11-7 18:36 | 显示全部楼层
mintspring 发表于 2016-11-1 22:09
用P1的8个端口作为并口发送数据给液晶屏。

是这样的,用哪些都行,看情况。
heisexingqisi 发表于 2016-11-7 18:45 | 显示全部楼层
这些常用的液晶屏的控制必须的掌握基本技能。
zhuomuniao110 发表于 2016-11-7 23:04 | 显示全部楼层
开发板挺小的,适合嵌入到自己DIY里面。
mintspring 发表于 2016-11-10 17:19 | 显示全部楼层
这种面包板还是很不错的。我有两个。
slotg 发表于 2016-11-10 23:50 | 显示全部楼层
感谢分享
 楼主| dongnanxibei 发表于 2016-11-11 11:31 | 显示全部楼层
有用的就拿去,不用谢
dlfyf 发表于 2016-11-28 10:46 | 显示全部楼层
请问楼主你芯片和液晶引脚接口接上拉电阻了没?
springvirus 发表于 2016-11-28 12:40 | 显示全部楼层
xzanne 发表于 2016-11-28 16:31 | 显示全部楼层
huangcunxiake 发表于 2016-12-4 15:32 | 显示全部楼层
如今我手里还有4个LCD1602呢,当年学习时候买的。
 楼主| dongnanxibei 发表于 2016-12-6 18:31 | 显示全部楼层
这个很流行的,初学者通常用这个液晶屏
 楼主| dongnanxibei 发表于 2016-12-6 18:33 | 显示全部楼层
利用这个可以做简单的图形界面,不过分辨率不高,现在简单的字符很OK,一般内置了数字字母等字形。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

225

主题

3848

帖子

18

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