您的位置:首页 > 编程语言 > C语言/C++

stm32的1602操作显示

2013-11-02 18:34 856 查看
第一次,移植8051的代码发现不成功

经过多次测试,IO输出的电压稳定时间跟8051不同,得做延时在5V,10K上拉的情况下,GPIO需重新配置

/********************************************************************

接口1:void lcd1602dis(uchar *dis1,uchar address1,uchar n)
详细: dis1第一行显示数据指针,要写入address1第X行的首位置,n为写入字符数
每行只能40字节最多  0位置-39位置    第一行:0x00-0x27    第二行:0x40-0x67
一次运行       n为忙碌返0平均次数,i为每行写入次数
接口2:void itp_lcd1602dis(uchar *dis1,uchar address1,uchar n)
详细:  中断中为避免重调用的显示函数    其余同上
接口3:void flash(uchar j,uchar d)
详细:    功能j次闪烁,间隔d毫秒     不返还CPU
接口4:void lcd_clr()
详细:  清屏	 一次运行
接口5: void lcd_init()
详细:  初始化  运行
********************************************************************/

/********************************************************************
注:硬件接口:插口在显示屏上端插入,P0为数据端,RS = P2^6   RW = P2^5  EN = P2^7
********************************************************************/
u8 nop;
#define no_oper nop=~nop;
#include "stm32f10x_lib.h"
extern void GPIO_Configuration2(void);
extern void Uart1_PutString(u8* buf , u8 len);
#define uchar unsigned char
#define uint  unsigned int
#define ulong  unsigned long
#define u8 unsigned char
#define u16  unsigned int

u8 display2[]="inithalf";
u8 display1[]="wdatbusydone";
u8 tmpdis;
/*#define LCD_RS    //= P2^6;
#define LCD_RW    //= P2^5;
#define LCD_EN    //= P2^7;*/
/********************************宏定义*********************************/
#define    P0i(x)      GPIO_Write(GPIOA, (uint)x);
#define    P0o(x)      x=(u8)(0x0011&GPIO_ReadInputData(GPIOA));
//控制孔得PP输出
#define    LCD_RS(x)  x ? GPIO_SetBits(GPIOB, GPIO_Pin_1): GPIO_ResetBits(GPIOB, GPIO_Pin_1)
#define    LCD_RW(x)  x ? GPIO_SetBits(GPIOB, GPIO_Pin_2): GPIO_ResetBits(GPIOB, GPIO_Pin_2)
#define    LCD_EN(x)  x ? GPIO_SetBits(GPIOB, GPIO_Pin_0): GPIO_ResetBits(GPIOB, GPIO_Pin_0)   //如此能延长单步时间,达到51 I/O读取时间
//P0为数据口
/*1。“code”是单片机C语言特有的关键字在单片机中RAM的空间特别小,特别珍贵。RAM空间,存放变量。
而一些常量,比如码表等常量放在ROM中。所以单片机中code就是告诉单片机这个数据放入ROM中。
本例中dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; 数组内容为常量,故加上code,以节约RAM的空间。
其实code放在unsigned char 前也可以,比如code unsigned char dispbit[8]效果一样*/
//uchar code dis1[]         //uchar 正好为ASCII码 8位一字节

//8051片内数据存储器除RAM(00-7fh)之外,还有特殊功能寄存其SFR(80H-FFH),两者合起来共有256字节,但是能够真正用来当数据寄存器的只有128字节,也就是RAM。

void NOP()
{ vu16 i;
for(i=0; i<100; i++);
}
void nop_stm32()
{ u8 i;
for(i=0; i<6; i++);
}
void nop6()
{ u8 i;
for(i=0; i<6; i++);
}
void nop12()
{ u8 i;
for(i=0; i<12; i++);
}
void nop24()
{ u8 i;
for(i=0; i<24; i++);
}
void nop48()
{ u8 i;
for(i=0; i<48; i++);
}

/*******************************************************************/
/*
延时子程序
*/
/*******************************************************************/

void delaylcd(int ms)
{
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
nop_stm32();
nop_stm32();
nop_stm32();
nop_stm32();
}
}
}

/*******************************************************************/
//
//检查LCD忙状态
//lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。
//
/*******************************************************************/
u8 lcd_busy()              //timepass:
{
u8 result;
LCD_RS(0);
LCD_RW(1);
LCD_EN (1);
nop_stm32();
nop_stm32();
nop_stm32();
nop_stm32();
result = (u8)(GPIO_ReadInputData(GPIOA)&0x0080);
LCD_EN(1);                             //目的达到后就不管时序图上标拉回 ?!!!必须拉回,问题就出在以前考察发现的地方
nop48();
LCD_EN(0);
return result;
}

/*******************************************************************/
//
//写指令数据到LCD
//RS=L,RW=L,E=高脉冲,D0-D7=指令码。
//
/*******************************************************************/

void lcd_wcmd(uchar cmd)    //     (16+k*11)us
{
while(lcd_busy());   //持续n*11us  //?是否计数以防:因lcd坏死程序进入死循环
LCD_RS(0);
nop_stm32();
nop_stm32();
LCD_RS(0);
LCD_RW(0);
nop_stm32();
nop_stm32();

LCD_EN(0);
nop12();

P0i(cmd);
nop48();
nop24();
LCD_EN(1);
//用nop48(),不仅收不到位置命令且还有显示出来
NOP();
LCD_EN(0);

}

/*******************************************************************/
//
//写显示数据到LCD
//RS=H,RW=L,E=高脉冲,D0-D7=数据。
//
/*******************************************************************/

void lcd_wdat(uchar dat)                           //(14+k*11)us
{
while(lcd_busy());    //持续n*11us  //?是否计数
//Uart1_PutString(&display1[0] , 12);

LCD_RS(1);
nop_stm32();
nop_stm32();
LCD_RS(1);
LCD_RW(0);

nop_stm32();
nop_stm32();
LCD_EN(0);
nop_stm32();  // only nop6() needed	?
nop_stm32();

b362
//GPIO_Write(GPIOA, (u16)0x31);
P0i(dat);
nop_stm32();

LCD_EN(1);// = 1;
NOP();
LCD_EN(0);// = 0;
NOP();
}

/*******************************************************************/
//
//  设定显示位置
//
/*******************************************************************/

void lcd_pos(uchar pos)                  //     (17+k*11)us
{
lcd_wcmd(pos|0x80);      //数据指针=80+地址变量  1XXXXXXX设置DDRAM地址
}

/*******************************************************************/
//
//  LCD初始化设定
//
/*******************************************************************/

void lcd_init()             //45ms
{
delaylcd(15);                     //等待LCD电源稳定
lcd_wcmd(0x38);          //16*2显示,5*7点阵,8位数据 //功能设置
delaylcd(5);
lcd_wcmd(0x38);
delaylcd(5);
lcd_wcmd(0x38);
delaylcd(5);
// Uart1_PutString(&display2[0] , 8);
lcd_wcmd(0x0c);          //显示开,关光标
delaylcd(5);
lcd_wcmd(0x06);          //移动光标
delaylcd(5);
lcd_wcmd(0x01);          //清除LCD的显示内容
delaylcd(5);
}

/*******************************************************************/
//
//  清屏子程序
//
/*******************************************************************/

void lcd_clr()                    //5ms
{
lcd_wcmd(0x01);          //清除LCD的显示内容
delaylcd(5);
}

/*******************************************************************/
//
//  闪动子程序
//
/*******************************************************************/

void flash(uchar j,uchar d)  //600+j*2*d ms   闪烁
{
uchar ii; //此句uchar 必须在delaylcd前
delaylcd(600);

for(ii;ii<j;ii++)
{
lcd_wcmd(0x08);            //关闭显示
delaylcd(d);                    //延时
delaylcd(d);
delaylcd(d);
lcd_wcmd(0x0c);            //开显示
delaylcd(d);
delaylcd(d);
delaylcd(d);
delaylcd(d);
}

}

/*******************************************************************/
//
//  主程序
//
/*******************************************************************/

void lcd1602dis(uchar *dis,uchar address,uchar n)      //19*n+17 + (n+1)*k*11 us  是否统计计算k的平均值
{
uchar i;
//delaylcd(1);

lcd_pos(address);               //设置显示位置为第一行第17列   第一行为 0x00-0x27  40个字节
i = 0;
//NOP();

while((dis[i] != '\0')&&(n!=0))
{
lcd_wdat(dis[i]);     //显示字符"         "
// NOP();
tmpdis=i+0x30;
// Uart1_PutString(&tmpdis,1);
n--;i++;
}
}

void itp_lcd1602dis(uchar *dis,uchar address,uchar n)
{
uchar i;
lcd_pos(address);              //第二行为 0x40-0x67  40个字节
i = 0;

while((dis[i] != '\0')&&(n!=0))     //\0是C++中字符串的结尾标志,存储在字符串的结尾。比如char cha[5]表示可以放5个字符的数组,由于c/c++中规定字符串的结尾标志为'\0',它虽然不计入串长,但要占内存空间
{
lcd_wdat(dis[i]);     //显示字符"         "
n--;i++;
}

/*    for(j=0;j<16;j++)           //向左移动16格
{
lcd_wcmd(0x18);           //字符同时左移一格
delaylcd(100);}                   //控制移动时间
*/

//flash();                            //闪动二次
}

//另外GPIO的配置
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;  //所有GPIO为同一类型端口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //GPIO_Mode_AF_PP 复用推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //输出的最大频率为50HZ
GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA端口
GPIO_Init(GPIOB, &GPIO_InitStructure);   //初始化GPIOB端口

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; //所有GPIO为同一类型端口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //输出的最大频率为50HZ
GPIO_Init(GPIOA, &GPIO_InitStructure);

//转为USART1配置串口接口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    //输入没有复用不复用
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //配置上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);

GPIO_Write(GPIOA,0xffff);  //将GPIOA 16个端口全部置为高电平
GPIO_Write(GPIOB,0xffff);  //将GPIOB 16个端口全部置为高电
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  1602 c语言 stm32 单片机