void LCD_Check_Busy(void) { static u16 busytimeout; //忙超时
//===================================================== LCDDataBus_IN(); //把数据引脚定义为浮空输入 do { busytimeout++; if(busytimeout > 300) break; LCD_RS = 0; LCD_Delay(); LCD_RW = 1; LCD_Delay(); LCD_EN = 1; LCD_Delay(); }while(GPIO_ReadInputData(DataBusGPIO) & DataBusPin7); //等待LCD忙完 LCD_EN = 0; LCDDataBus_OUT(); //把数据引脚定义为输出
//===================================================== if(busytimeout >= 300) printf(\ busytimeout = 0; }
/**********************************************************
* 函数功能 ---> LCD写入一个字节命令或者数据,判断忙标志(8位数据一次发送完毕) * 入口参数 ---> dat:要写入的字节
* ord:判断dat是命令还是数据依据,“0”为命令,“1”为数据 * 返回数值 ---> none * 功能说明 ---> none
**********************************************************/ void LCD_Write_Byte(u8 dat,u8 ord) {
//=====================================================
LCD_Check_Busy(); //判断是否在忙? LCD_EN = 0; LCD_Delay(); LCD_RW = 0; LCD_Delay();
if(ord & 0x01) LCD_RS = 1; //放上数据或者命令判断位 else LCD_RS = 0; LCD_EN = 1; LCD_Delay(); LCDWriteData(dat); //放入数据 LCD_Delay(); LCD_EN = 0;
//===================================================== }
//=========================================================
#else //没定义则使用串口通讯模式
#ifdef LCD_Work_Mode_HardSPI //串行模式-采用硬件SPI
//========================================================= /**********************************************************
* 函数功能 --->初始化硬件SPI1模块,配置为主机模式 * 入口参数 ---> none * 返回数值 ---> none * 功能说明 ---> none
**********************************************************/ void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,
ENABLE); //使能GPIOB时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //使能SPI1时钟 //GPIOB3,5初始化设置(仅使用SCK,MOSI引脚) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5; //PB3~5复用功能输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed =
GPIO_Speed_100MHz; //100MHz //上拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB,
&GPIO_InitStructure);
//初始化 GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3复用为 SPI1(SCK)
//GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4复用为 SPI1(MISO)
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5复用为 SPI1(MOSI) //这里只针对SPI口初始化
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE); //复位SPI1 RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE); //停止复位SPI1
SPI_InitStructure.SPI_Direction
=
SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 //LCD1286时钟为上升沿有效,而且必须保证第一个上升沿也有数据,这里是调试的难点 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个上升沿数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler =
SPI_BaudRatePrescaler_2; //定义波特率预分频的值:波特率预分频值为16 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(SPI1, ENABLE); //使能SPI外设
据
}
/**********************************************************
* 函数功能 ---> LCD写入一个字节命令或者数据 * 入口参数 ---> dat:要写入的命令或者数据
* ord:命令或者数据判断为。0为命令,1为数
* 返回数值 ---> none * 功能说明 ---> none
**********************************************************/ void LCD_Write_Byte(u8 dat,u8 ord) { u8 lcd_data_msb,lcd_data_lsb; lcd_data_msb = 0xf0&dat; lcd_data_lsb = (0x0f&dat)<<4;
if(ord == 0)//写命令 {
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET); //等待SPI1发送缓存空
SPI_I2S_SendData(SPI1,0xf8); //SPI1发送数据--命令指令-- }
else//写数据 {
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET); //等待SPI1发送缓存空
SPI_I2S_SendData(SPI1,0xfa); //SPI1发送数据--数据指令 } LCD_delay_nus(73); //LCD12864响应时间73us while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//等待SPI1发送缓存空 SPI_I2S_SendData(SPI1,lcd_data_msb); //SPI1发送数据--数据指令 LCD_delay_nus(73); //LCD12864响应时间73us while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//等待SPI1发送缓存空 SPI_I2S_SendData(SPI1,lcd_data_lsb); //SPI1发送数据--数据指令 LCD_delay_nus(73); //LCD12864响应时间73us }
//========================================================= #else //GPIO模拟SPI //========================================================= /**********************************************************
* 函数功能 ---> LCD启动字节 * 入口参数 ---> dt:传输的字节,高5位在函数内部设定为1 * 只是确定RW和RS为,最后那位也是内部确定 * 返回数值 ---> none * 功能说明 --->首先传送一个启动字节,送入连续5个“1”用来启 * 动一个周期,此时传输计数被重置,并且串行传输 * 被同步,紧接着的两个位指定传输方向(R/W,确 * 定是读还是写)和传输性质(RS,确定是命令寄存 * 器还是数据寄存器),最后的第八位是一个“0” **********************************************************/ void LCD12864_Start(u8 dt) { u8 dat,j; dat = dt | 0xf8; //高5位设定为“1”,第八位设定为“0” LCD_SCL = 0; LCD_Delay();LCD_Delay();
LCD_CS = 1; //选中显示屏,高电平有效 for(j = 0;j < 8;j++) {
LCD_SCL = 1; //发送数据,上升沿有if(dat & 0x80) LCD_SDA = 1; //放数据到else LCD_SDA = 0;
数据线 LCD_Delay();LCD_Delay();LCD_Delay(); 效