搜索
您的当前位置:首页正文

STM32串行驱动12864液晶

来源:星星旅游


自己参考大神们的程序改写的液晶驱动,希望对有需要的人能有帮助

#include \"stm32f10x.h\"

static __IO uint32_t TimingDelay;

void RCC_Configuration(void);

void Delay(__IO uint32_t nTime);

#define Line1 0x80//液晶第一行

#define Line2 0x90//液晶第二行

#define Line3 0x88//液晶第三行

#define Line4 0x98//液晶第四行

#define LCD_IO GPIOE //我用的是 E.2 E.3 E.4 E.5 E.6

#define CS GPIO_Pin_2

#define RW GPIO_Pin_3

#define CLK GPIO_Pin_4

#define PSB GPIO_Pin_5

#define RST GPIO_Pin_6

#define SET(n) GPIO_SetBits(GPIOE,n) //将对应管脚输出高电平

#define RESET(n) GPIO_ResetBits(GPIOE,n)//输出低电平

#define CMD (uint32_t)0xf8000000 //串行 写入的是命令要先写入0xf8

#define DATE (uint32_t)0xfa000000 // 串行 写入数据要先写入0xfa

void LCD_IOinit_OUT() //推挽输出模式 ,管脚配置,不多解释,库函数有

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin =CS|RW|CLK|PSB|RST;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(LCD_IO, &GPIO_InitStructure);

}

void LCD_Write(uint32_t cmd,uint8_t ddata)//LCD 写函数

{

uint32_t temp=cmd;

uint32_t i;

RESET(CS); //片选拉低

temp|=((uint32_t)(ddata&(uint8_t)0xf0)<<16)+((uint32_t)(ddata&(uint8_t)0x0f)<<12);

SET(CS); //片选拉高,开始传输数据

for(i=0;i<24;i++)

{

if(temp&0x80000000)SET(RW); //取出最高位,如果是1,那么RW就写1

else RESET(RW); //如果是0 RW就写0

SET(CLK);//向液晶写数据 是在下降沿写入的

Delay(2);//稍作延时

RESET(CLK);//拉低产生下降沿,写入数据

temp=temp<<1;//左移一位 ,写入下一位

}

RESET(CS); //拉低片选,写入数据完毕

}

void Display(uint8_t addr,uint8_t *hz)

{

LCD_Write(CMD,addr);

Delay(3);

while(*hz!='\\0')

{

LCD_Write(DATE,*hz);

hz++;

Delay(3);

}

}

void LCD_init()//液晶初始化

{

RESET(CS); //拉低片选

RESET(PSB);//PSB拉低,表示是串行,拉高则是并行

RESET(RST);//拉低RST

Delay(100);

SET(RST);

Delay(40);

LCD_Write(CMD,0x30);//8位数据传输

Delay(40);

LCD_Write(CMD,0x0c);//显示开,游标开

Delay(40);

LCD_Write(CMD,0x01);//清屏

Delay(40);

LCD_Write(CMD,0x06);//进入点设定 AC+1

Delay(40);

}

int main()

{

RCC_Configuration();

SysTick_Config(72000); //配置SYSTICK时钟节拍为1ms一次

LCD_IOinit_OUT();

LCD_init();

while(1)

{

Display(Line1,\"你妹\");

Display(Line2,\"你妹\");

Display(Line3,\"你妹妹\");

Display(Line4,\"完事了,哈哈哈哈哈\");

}

}

void RCC_Configuration(void)

{

SystemInit();

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE , ENABLE);

}

void Delay(__IO uint32_t nTime)

{

TimingDelay = nTime;

while(TimingDelay != 0);

}

void TimingDelay_Decrement(void)

{

if (TimingDelay != 0x00)

{

TimingDelay--;

}

}

/*

temp|=((uint32_t)(ddata&(uint8_t)0xf0)<<16)+((uint32_t)(ddata&(uint8_t)0x0f)<<12);

重点解释一下这里,从串行时序图中可以看出,发送一个指令需要三个字节,第一个是0xf8或者0xfa这个根据你要发送的是命令还是数据而定,然后发送下一个数据的高四位和第四位,但是数据都是在高四位上面,用51的话我们要分三次发送,但是32的话一个字节可以是32位的/所以我们一次就能完成,这也是为什么下面的i<24的原因因为最后的8位没有用,

例如:我们发送指令0x35,则应该是这样0xf8然后0x30然后0x50,这个应该很好理解

所以看一下上面的语句首先我们cmd的值应该为0xf8000000,这个宏定义有的,这是发送命令然后我们让cmd=temp;在把temp和后面的计算结果做按位或运算.首先看这个(uint32_t)(ddata&(uint8_t)0xf0)<<16)我们的ddtate是0x35他和0xf0按位与之后/变为0x30然后左移16位变成0x30 0000;再强制转换为32位,就把高位补零变为0x00 30 0000再看这句话(uint32_t)(ddata&(uint8_t)0x0f)<<12)我们的ddtate是0x35

他和0x0f按位与/之后变为0x05,左移12位 0x05 000 强制转换为32位 高位补零 0x000 05 000 /在和前面的相加就是 0x00 30 0000+0x000 05 000=0x0030 5000然后在和前面的0xf8000000按位或变为0xf830 5000 液晶读这个数据的时候是 八位八位的读取 所以在液晶看来 是分四次的0xf8 0x30 0x50 0x00显然后八位没用 所以我们只取前面的24位

//应该能看懂了把言

*/

结合时序图还有延时一定要精确大家有看不懂的可以给我留

因篇幅问题不能全部显示,请点此查看更多更全内容

Top