- #include <M051Series.h>
- #define PLLCON_SETTING SYSCLK_PLLCON_50MHz_XTAL
- #define PLL_CLOCK 50000000
- //#define LCD1602_BUS_NUM 8 //8位数据总线,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的数据总线
- #define LCD1602_RS P30 // LCD1602的RS
- #define LCD1602_RW P31 // LCD1602的RW
- #define LCD1602_E P32 // LCD1602的E控制线
- #define LCD1602_Busy P17 // 定义LCD1602的测忙线,应该是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进行调光。
- /* 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忙程序 [底层协议] // (所有底层协议都无需关注)
- // LCD1602测忙,若LCD1602处于忙状态,本函数将等待至非忙状态
- //********************************************************************************************/
- void LCD1602_TestBusy(void){
- LCD1602_DATA_PORT = 0xff; //设备读状态
- 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写入一个指令或者数据
- //R_S 1是数据 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);//送入高四位数据
- SYS_SysTickDelay(5);
- LCD1602_E = 1;
- SYS_SysTickDelay(5);
- LCD1602_E = 0;
- LCD1602_DATA_PORT &= 0x0f; //高四位清0
- LCD1602_DATA_PORT|=(byte<<4&0xf0);//送入低四位数据
- SYS_SysTickDelay(5);
- LCD1602_E = 1;
- SYS_SysTickDelay(5);
- LCD1602_E = 0;
- #endif
- }
- //********************************************************************************************
- // 写指令程序 //
- // 向LCD1602写命令 本函数需要1个指令集的入口参数 //
- //********************************************************************************************/
- void LCD1602_WriteCMD(uint8_t LCD1602_command) {
- LCD1602_WriteByte(0x00,LCD1602_command);
- }
- //********************************************************************************************
- // 写数据程序 //
- // 向LCD写数据 //
- //********************************************************************************************/
- void LCD1602_WriteData(uint8_t LCD1602_data){
- LCD1602_WriteByte(0x01,LCD1602_data);
- }
- //设置光标位置,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);
- }
- //********************************************************************************************
- // 打印字符串程序 // (本函数调用指针函数)
- //在第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个像素
- //需要设置两次
- LCD1602_WriteCMD(0x28); // 4总线,显示2行,每个字符为5*7个像素
- #endif
- LCD1602_WriteCMD(0x01); // 显示清屏
- LCD1602_WriteCMD(0x02); // 数据指针指向第1行第1个字符位置
- LCD1602_WriteCMD(0x06); // 显示光标移动设置:文字不动,光标右移
- LCD1602_WriteCMD(0x0c); // 显示开及光标设置:显示开,光标开,闪烁开
- }
- 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)
- {
- }
- }
|