最近比较忙,过段时间就要考期末了,所以半夜出来发代码,后面可能没时间了,发完代码睡觉,呵呵。
相信用过1602的人都知道,1602的相应操作,本文只想讲下4位数据的1602的驱动模式。
其实,4位的1602和8位的区别主要如下:
8位,待写的数据一次送到液晶D7~D0;4位,待写数据分2次送液晶D7~D4,先高4位,然后低4位左移4位后再送D7~D4 ;也就是说4位模式只要占用高四位的引脚就可以了,这样可以节省IO资源,呵呵,对于IO资源特别紧缺的单片机来说是一个好消息,呵呵,下面上原理图:
#include "stm32f10x_lib.h"
void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); void delay(void); void lcd_delay(void) { unsigned short n; n= 30; while(n) {n--;} }
void lcd_delay_long(void) { unsigned short n; n= 1850; while(n) {n--;} }
//LCD 传送指令 void lcd_sendorder(unsigned char data) { unsigned short temp;
GPIO_ResetBits(GPIOA, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_10); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); lcd_delay(); //输出数据,高4位 temp = data; temp = temp & 0x00f0; temp = temp << 8;
GPIO_SetBits(GPIOB, temp); temp = ~temp; temp = temp & 0xf000; GPIO_ResetBits(GPIOB, temp); //第一次 E 信号 GPIO_SetBits(GPIOB, GPIO_Pin_11); lcd_delay(); lcd_delay(); lcd_delay(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); lcd_delay(); //输出数据,低4位 temp = data; temp = temp & 0x000f; temp = temp << 12;
GPIO_SetBits(GPIOB, temp); temp = ~temp; temp = temp & 0xf000; GPIO_ResetBits(GPIOB, temp);
//第二次 E 信号 GPIO_SetBits(GPIOB, GPIO_Pin_11); lcd_delay(); lcd_delay(); lcd_delay(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); lcd_delay(); //复原 各个信号 GPIO_ResetBits(GPIOA, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_10); GPIO_ResetBits(GPIOB, GPIO_Pin_11); GPIO_SetBits(GPIOB, 0xf000);
lcd_delay_long(); lcd_delay_long(); }
//向LCD 传送字符数据 void lcd_senddata(unsigned char data) { unsigned short temp;
GPIO_SetBits(GPIOA, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_10); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); //输出数据,高4位 temp = data; temp = temp & 0x00f0; temp = temp << 8;
GPIO_SetBits(GPIOB, temp); temp = ~temp; temp = temp & 0xf000; GPIO_ResetBits(GPIOB, temp); //第一次 E 信号 lcd_delay(); GPIO_SetBits(GPIOB, GPIO_Pin_11); lcd_delay(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); //输出数据,低4位 temp = data; temp = temp & 0x000f; temp = temp << 12;
GPIO_SetBits(GPIOB, temp); temp = ~temp; temp = temp & 0xf000; GPIO_ResetBits(GPIOB, temp);
//第二次 E 信号 lcd_delay(); GPIO_SetBits(GPIOB, GPIO_Pin_11); lcd_delay(); GPIO_ResetBits(GPIOB, GPIO_Pin_11); lcd_delay(); //复原 各个信号 GPIO_ResetBits(GPIOA, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_10); GPIO_ResetBits(GPIOB, GPIO_Pin_11); GPIO_SetBits(GPIOB, 0xf000); lcd_delay(); lcd_delay_long(); lcd_delay_long();
}
//LCD 整体复位 void lcd_reset(void) { lcd_delay_long(); lcd_sendorder(0x3c); //4位模式,两行, lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x14); //光标右移 lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x40); //CG 复位 lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x0C); //开显示,关闭光标 lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x06); //数据操作后,位置自动加一 lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x02); //光标回0 lcd_delay_long(); lcd_delay_long(); lcd_sendorder(0x01); //清屏 lcd_delay_long(); lcd_delay_long();
}
//LCD 清屏 void lcd_cls(void) { lcd_delay(); lcd_sendorder(0x01); //清屏 lcd_delay_long();
}
//LCD 光标定位 void lcd_locate(unsigned char address) { lcd_delay(); lcd_sendorder(0x80|address); //清屏 lcd_delay();
}
//显示字符串,字符串、显示数量 void lcd_putchar(unsigned char *data, unsigned char number) { while(number) { lcd_senddata( *data ); lcd_delay();
number --; data++; } }
//显示数字,数据、位数 void lcd_putnum(signed int data, unsigned char number) { unsigned char num[10],n; if(data <0) { lcd_senddata(0x2d); data = 0 - data; number--; } n=0; while(number > n) { num[n] = ( data % 10 ) + 0x30; n++; data = data / 10; } while(n) { n--; lcd_senddata(num[n]); } }
int main(void) { #ifdef DEBUG debug(); #endif
RCC_Configuration(); //配置系统时钟
NVIC_Configuration();//配置 NVIC 和 Vector Table
GPIO_Configuration(); //使用的GPIO口 delay(); //主循环 delay(); lcd_reset(); lcd_cls(); lcd_locate(0x04); lcd_putchar("HELLO,EEWORLD!",14); lcd_locate(0x40); lcd_putchar("This is eeworld",15); //lcd_putnum(-8734,5); while (1) { } }
void RCC_Configuration(void) { ErrorStatus HSEStartUpStatus; RCC_DeInit();//将外设 RCC寄存器重设为缺省值
RCC_HSEConfig(RCC_HSE_ON); //设置外部高速晶振(HSE) HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待 HSE 起振
if(HSEStartUpStatus == SUCCESS) { FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预取指缓存使能
FLASH_SetLatency(FLASH_Latency_2); //设置代码延时值 FLASH_Latency_2 2 延时周期
RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置 AHB 时钟(HCLK)RCC_SYSCLK_Div1 AHB 时钟 = 系统时钟 RCC_PCLK2Config(RCC_HCLK_Div2); //设置高速 AHB 时钟(PCLK2)RCC_HCLK_Div2 APB1 时钟 = HCLK / 2 RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速 AHB 时钟(PCLK1)RCC_HCLK_Div2 APB1 时钟 = HCLK / 2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // PLLCLK = 8MHz * 9 = 72 MHz 设置 PLL 时钟源及倍频系数 RCC_PLLCmd(ENABLE);//使能或者失能 PLL while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) //等待指定的 RCC 标志位设置成功 等待PLL初始化成功 { } RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK) 设置PLL为系统时钟源 while(RCC_GetSYSCLKSource() != 0x08) //等待PLL成功用作于系统时钟的时钟源 0x00:HSI 作为系统时钟 0x04:HSE作为系统时钟 0x08:PLL作为系统时钟 { } }
//使能或者失能 APB2 外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); }
void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; //LCD 端口设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init(GPIOA, &GPIO_InitStructure); }
void NVIC_Configuration(void) { #ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #endif }
void delay() { int i; for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); for (i=0; i<0xffff; i++); }
#ifdef DEBUG
void assert_failed(u8* file, u32 line) { while (1) { } } #endif
|