我们经常会因为让PCB layout更好布线、IO口数量、遗漏或者其它原因,使用8个不连续的端口,而我们的程序通常是固化的,比如你在LCD1602中8个数据端分布在IGROA,IGROB,IGROC中,这个问题是经常出现 的不论你是用51还是STM32,这个时候你套用以前的1602程序是不行的,那么怎么解决呢,叫让单片机终结者来给你写个程序参考一下吧。 思路: 1、配置IO口 2、引入8个连续的新的端口D0,D1,D2,D3,D4,D5,D6,D7 3、把一个16进制数或者10进制数移位给D0,D1,D2,D3,D4,D5,D6,D7 main.c中 #include "gpio.h" #include "delay.h" #include "sys.h" #include "1602.h" #include "stm32f10x_gpio.h" #include "stm32f10x_it.h" #include "stm32f10x_flash.h" int main(void) { delay_init(); //延时初始化 gpio_init(); //IO初始化 lcd_Init(); //液晶初始化 Display_Init(); //液晶初始化赋值 while(1) { Display_test(); } } } 1602.h #ifndef __1602_H #define __1602_H #include "sys.h" typedef struct{ u32 weight_value; }smart_balance_para; #define RS GPIO_Pin_11 #define RW GPIO_Pin_2 #define EN GPIO_Pin_10 #define D0 PBout(0) #define D1 PBout(1) #define D2 PCout(4) #define D3 PCout(5) #define D4 PAout(6) #define D5 PAout(7) #define D6 PAout(4) #define D7 PAout(5) #define LCD_RS(x) x ? GPIO_SetBits(GPIOB, RS): GPIO_ResetBits(GPIOB, RS) #define LCD_RW(x) x ? GPIO_SetBits(GPIOB, RW): GPIO_ResetBits(GPIOB, RW) #define LCD_EN(x) x ? GPIO_SetBits(GPIOB, EN): GPIO_ResetBits(GPIOB, EN) void lcd_Init(void); void lcd_wcmd(u8 cmd); void lcd_pos(unsigned char pos); void lcd_wdat(u8 dat); void LCD_Setpos(unsigned char row,unsigned char col); void Display(u32 val); void LCD_DispChar(unsigned char ch); void LCD_DispString(char str[]); void LCD_Setpos_DispString(unsigned char row,unsigned char col,char str[]); void LCD_Dispnum(unsigned int num); void LCD_Dispnum_fu(int32 num); void Display_test(void); void Display_Init(void); void Display_adjust(int32 val); #endif 1602..c #include "stm32f10x.h" #include "1602.h" #include "Time.h" #include "delay.h" #include <stdlib.h> extern int32 sx; char dis6[] = {"Loading:"}; char dis7[] = {"12345678"}; char dis8[] = {"87654321"}; static int reverse_bit(int num) { int i; int bit; int new_num = 0; for (i = 0; i < 8; i++) { bit = num & 1; // new_num <<= 1; // new_num =new_num | bit; // num >>= 1; } return new_num; } /******************************写命令*************************************************/ void lcd_wcmd(u8 cmd) { // 写入指令数据到LCD u16 cmd_tmp ; // 写入指令数据到LCD LCD_RS(0); // 0; LCD_RW(0); // 0; D0=(cmd>>0)&0x01; D1=(cmd>>1)&0x01; D2=(cmd>>2)&0x01; D3=(cmd>>3)&0x01; D4=(cmd>>4)&0x01; D5=(cmd>>5)&0x01; D6=(cmd>>6)&0x01; D7=(cmd>>7)&0x01; LCD_EN(1); // 0; LCD_EN(0); // 0; delay_us(50); } /******************************设置位置*************************************************/ void lcd_pos(unsigned char pos) { //设定显示位置 lcd_wcmd(pos | 0x80); } /******************************设置位置*************************************************/ void lcd_wdat(u8 dat) { //写入字符显示数据到LCD u16 dat_tmp; LCD_RS(1); //= 1; LCD_RW(0); //= 0; D0=(dat>>0)&0x01;//移位 87654321中的1移位到D0 D1=(dat>>1)&0x01; D2=(dat>>2)&0x01; D3=(dat>>3)&0x01; D4=(dat>>4)&0x01; D5=(dat>>5)&0x01; D6=(dat>>6)&0x01; D7=(dat>>7)&0x01;//移位 87654321中的8移位到D7 LCD_EN(1); //= 0; LCD_EN(0);// = 1; delay_us(50); } void lcd_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO, ENABLE); // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_2 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50MHZ GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50MHZ GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 ; //所有GPIO为同一类型端口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为5M0HZ GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; //所有GPIO为同一类型端口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出的最大频率为50MHZ GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC端口 GPIO_InitStructure.GPIO_Pin = 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; //输出的最大频率为50MHZ GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA端口 GPIO_Write(GPIOA,0XFFFF); //将GPIOB 16个端口全部置为高电 GPIO_Write(GPIOB,0XFFFF); //将GPIOB 16个端口全部置为高电 GPIO_Write(GPIOC,0XFFFF); //将GPIOB 16个端口全部置为高电 GPIO_SetBits(GPIOB,GPIO_Pin_2); GPIO_SetBits(GPIOB,GPIO_Pin_11); lcd_wcmd(0x38); //显示模式设置 delay_ms(5); lcd_wcmd(0x38); //显示模式设置 delay_ms(5); lcd_wcmd(0x38); //显示模式设置 delay_ms(5); lcd_wcmd(0x38); //显示模式设置 lcd_wcmd(0x08); //显示关闭 lcd_wcmd(0x01); //显示清屏 lcd_wcmd(0x06); //显示光标移动设置 delay_ms(5); lcd_wcmd(0x0C); //显示开及光标设置 } void Display_test(void) { LCD_Setpos(1,0); LCD_DispString(dis7); LCD_Setpos(2,0); LCD_DispString(dis8); } void Display_Init(void) { Display_overKG(); LCD_Setpos(1,0); LCD_DispString(dis6); } void LCD1602_DisplayOneChar(unsigned char X,unsigned char Y,unsigned char ddata) { Y &= 0x01; X &= 0xf; if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; X |= 0x80; // 算出指令码 lcd_wcmd(X); //发送地址码 // LCD1602_BusyCheck(); lcd_wdat(ddata); } void LCD_Setpos(unsigned char row,unsigned char col) { if(row==1) lcd_wcmd(col | 0x80); else lcd_wcmd(col | 0xC0); } void LCD_DispChar(unsigned char ch) { lcd_wdat(ch); } void LCD_DispString(char str[]) { unsigned char i=0; while(str[i] != '\0') { lcd_wdat(str[i]); i++; delay_ms(1); } } void LCD_Setpos_DispString(unsigned char row,unsigned char col,char str[]) { LCD_Setpos(row,col); LCD_DispString(str); } 声明:本站所有内容,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。 收藏 链接