找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

新唐M051學(xué)習(xí)之(4)-LCD1602

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:75013 發(fā)表于 2015-3-21 17:45 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
根據(jù)原來用51單片機(jī)寫LCD160的經(jīng)驗今天用M051的程序重新整理了一遍,并把8位總線和4位總線的的程序整合到一起。從吃完晚飯就坐這,現(xiàn)在都11點多了,整整搞了一個晚上,廢話不多說了,抓緊寫完睡覺。
1602采用標(biāo)準(zhǔn)的16腳接口,其中:第1腳:VSS為電源地
第2腳:VCC接5V電源正極
第3腳:V0為液晶顯示器對比度調(diào)整端,接正電源時對比度最弱,接地電源時對比度最高,使用時可以通過一個10K的電位器調(diào)整對比度。我用的這款LCD直接接地,對比度是最佳的,省了不少事。
第4腳:RS為寄存器選擇,高電平1時選擇數(shù)據(jù)寄存器、低電平0時選擇指令寄存器。
第5腳:RW為讀寫信號線,高電平(1)時進(jìn)行讀操作,低電平(0)時進(jìn)行寫操作。
第6腳:E(或EN)端為使能端。
第7~14腳:D0~D7為8位雙向數(shù)據(jù)端。
第15腳:背光正極。
第16腳:背光負(fù)極。

下圖是LCD1602跟M0516的連接圖。4總線的D0-D3懸空,D4-D7分別接一個IO的高4位也就是第4-第7位。M0516的這個IO的低4位還可以正常作為其他用途,這樣就省了4個IO口。



下面是接8位總線的實物圖及顯示效果圖。



下面是接4位總線的實物圖及顯示效果圖。


#include <M051Series.h>
#define PLLCON_SETTING      SYSCLK_PLLCON_50MHz_XTAL
#define PLL_CLOCK           50000000

//#define LCD1602_BUS_NUM 8   //8位數(shù)據(jù)總線,DB0-DB7 按順序接到一個IO口的 0-7位
//4位總線,DB4 - DB7 按順序接到一個IO口的 4-7位,液晶上的DB0-DB3空著,IO口上的0-3位可以正常作為其他用途
#define LCD1602_BUS_NUM 4
#define    LCD1602_DATA_PORT        P1->DOUT            // LCD1602的數(shù)據(jù)總線
#define LCD1602_RS    P30               // LCD1602的RS
#define LCD1602_RW    P31               // LCD1602的RW
#define LCD1602_E     P32               // LCD1602的E控制線
#define LCD1602_Busy  P17                   // 定義LCD1602的測忙線,應(yīng)該是LCD1602_DB0_DB7的第8位IO口

void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
    /* Unlock protected registers */
    SYS_UnlockReg();
    /* Enable External XTAL (4~24 MHz) */
    SYSCLK->PWRCON |= SYSCLK_PWRCON_XTL12M_EN_Msk;
    /* Waiting for 12MHz clock ready */
    SYS_WaitingForClockReady( SYSCLK_CLKSTATUS_XTL12M_STB_Msk);
    /* Switch HCLK clock source to XTAL */
    SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_XTAL;

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

    /* Waiting for clock ready */
    SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);

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

    /* Enable IP clock */        
    SYSCLK->APBCLK = SYSCLK_APBCLK_PWM01_EN_Msk;
    /* IP clock source */
    SYSCLK->CLKSEL1 = SYSCLK_CLKSEL1_PWM01_XTAL;


    /* Reset PWMB channel0~channel3 */                    
    SYS->IPRSTC2 = SYS_IPRSTC2_PWM47_RST_Msk;                    
    SYS->IPRSTC2 = 0;      




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

/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* P2.0 for PWM0 */
    //P2.0接LCD1602的背光
    SYS->P2_MFP = SYS_MFP_P20_PWM0 ;
    /* Lock protected registers */
    SYS_LockReg();

}

void PWMA_Init(void)

{
    PWMA->PPR = PWM_PPR_CP01(30) ;
    PWMA->CSR = PWM_CSR_CSR0(PWM_CSR_DIV16);
    //P2.0接LCD1602的背光,可以用PWM進(jìn)行調(diào)光。
    /* Enable PWM0 counter. We must set PWM mode before setting CNR, CMR. */
    PWMA->PCR = PWM_PCR_CH0EN_Msk | PWM_PCR_CH0MOD_AUTO_RELOAD;
    /* PWM0 = 12000000 / 30 / 16 / 200 =    125Hz */
        PWMA->CNR0= 200;
    PWMA->CMR0= 180;

    /* Enable PWM channle 0 Output */
    PWMA->POE = PWM_POE_PWM0_Msk;
}

//********************************************************************************************
// 讀LCD忙程序 [底層協(xié)議] // (所有底層協(xié)議都無需關(guān)注)
// LCD1602測忙,若LCD1602處于忙狀態(tài),本函數(shù)將等待至非忙狀態(tài)
//********************************************************************************************/
void LCD1602_TestBusy(void){
    LCD1602_DATA_PORT = 0xff;       //設(shè)備讀狀態(tài)
    SYS_SysTickDelay(5);
    LCD1602_RS = 0;
    SYS_SysTickDelay(5);
    LCD1602_RW = 1;
    SYS_SysTickDelay(5);
    LCD1602_E = 1;
    while(LCD1602_Busy);        //等待LCD不忙
    LCD1602_E = 0;              //
}
//向LCD1602寫入一個指令或者數(shù)據(jù)
//R_S 1是數(shù)據(jù)  0是命令
void LCD1602_WriteByte(uint8_t R_S, uint8_t byte)
{
      LCD1602_TestBusy();
        LCD1602_RS = R_S;
        LCD1602_RW = 0;
        #if (LCD1602_BUS_NUM == 8)  //8位總線
            LCD1602_DATA_PORT = byte;
            SYS_SysTickDelay(10);
            LCD1602_E = 1;
            SYS_SysTickDelay(10);
            LCD1602_E = 0;
        #elif (LCD1602_BUS_NUM == 4) //4位總線
            LCD1602_DATA_PORT &= 0x0f; //高四位清0
            LCD1602_DATA_PORT |= (byte&0xf0);//送入高四位數(shù)據(jù)
            SYS_SysTickDelay(5);
            LCD1602_E = 1;
            SYS_SysTickDelay(5);
            LCD1602_E = 0;      

            LCD1602_DATA_PORT &= 0x0f; //高四位清0
            LCD1602_DATA_PORT|=(byte<<4&0xf0);//送入低四位數(shù)據(jù)
            SYS_SysTickDelay(5);
            LCD1602_E = 1;
            SYS_SysTickDelay(5);
            LCD1602_E = 0;      
        #endif
}
//********************************************************************************************
// 寫指令程序 //
// 向LCD1602寫命令 本函數(shù)需要1個指令集的入口參數(shù) //
//********************************************************************************************/
void LCD1602_WriteCMD(uint8_t LCD1602_command) {
    LCD1602_WriteByte(0x00,LCD1602_command);
}
//********************************************************************************************
// 寫數(shù)據(jù)程序 //
// 向LCD寫數(shù)據(jù) //
//********************************************************************************************/
void LCD1602_WriteData(uint8_t LCD1602_data){
    LCD1602_WriteByte(0x01,LCD1602_data);
}
//設(shè)置光標(biāo)位置,line表示第幾行,row表示第幾列
void LCD1602_SetXY(uint8_t line,uint8_t row)
{
    uint8_t addr;
    if(line>2 || line ==0) line = 1;
    if(row>40 || row == 0) row = 1;
    row +=0x80;
    if(line == 1)
        addr = row - 1;       //第一行
    else if(line == 2)
        addr = row - 1 + 0x40; //第二行
    LCD1602_WriteCMD(addr);
}
//********************************************************************************************
// 打印字符串程序 // (本函數(shù)調(diào)用指針函數(shù))
//在第x行 第y列 開始顯示字符串
//字符串最長48個
//********************************************************************************************/
void LCD1602_PrintString(uint8_t x,uint8_t y,char *str){
    LCD1602_SetXY(x,y);
    while(*str != 0){
        LCD1602_WriteData(*str++);
    }
}
//********************************************************************************************
// 打印單字符程序 //
//在第x行 第y列 顯示字符
//* *******************************************************************************************/
void LCD1602_PrintChar(uint8_t x,uint8_t y,char t){
        LCD1602_SetXY(x,y);
        LCD1602_WriteData(t);
}
//********************************************************************************************
// LCD初始化 //(使用者可自定義,加 * 號程序行必須保留但可修改)
//********************************************************************************************/
void LCD1602_Init(void){
    #if (LCD1602_BUS_NUM == 8) //8位總線
        LCD1602_WriteCMD(0x38); // 8總線,顯示2行,每個字符為5*7個像素
    #elif (LCD1602_BUS_NUM == 4) //4位總線
        LCD1602_WriteCMD(0x28); // 4總線,顯示2行,每個字符為5*7個像素
        //需要設(shè)置兩次
        LCD1602_WriteCMD(0x28); // 4總線,顯示2行,每個字符為5*7個像素
    #endif      
    LCD1602_WriteCMD(0x01); //  顯示清屏
    LCD1602_WriteCMD(0x02);     // 數(shù)據(jù)指針指向第1行第1個字符位置
    LCD1602_WriteCMD(0x06);     //  顯示光標(biāo)移動設(shè)置:文字不動,光標(biāo)右移
    LCD1602_WriteCMD(0x0c);     //  顯示開及光標(biāo)設(shè)置:顯示開,光標(biāo)開,閃爍開
}
int main(void)
{
    SYS_Init();
    PWMA_Init();
    LCD1602_Init();
    LCD1602_PrintString(1,3,"QQ:48469646");
    LCD1602_PrintString(2,1,"BUS:4");
    LCD1602_PrintChar(2,7,'O');
    LCD1602_PrintChar(2,8,'K');
    LCD1602_PrintChar(2,9,33);   //嘆號
    while(1)
    {
    }
}






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

使用道具 舉報

沙發(fā)
ID:75874 發(fā)表于 2015-4-1 11:51 | 只看該作者
我是香港百特集團(tuán),新塘單片機(jī)國內(nèi)一級代理商,需要學(xué)習(xí)或者購買的請聯(lián)系我QQ420607117tel18520898984
reguars!
回復(fù)

使用道具 舉報

板凳
ID:77562 發(fā)表于 2015-4-24 17:05 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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