今天对比了下KL46和K64的GPIO和PORT的寄存器,相差不大,可以直接移植,我就把OLED的程序移植到K64上显示。 另外KL系列的还有两种GPIO,一种是普通的 GPIO,另一种是高速的 GPIO(FGPIO)。 FGPIO 是单总线周期的工作模式,FGPIO可实现1-cycle单周期执行GPIO操作,因此用户在用软件模拟各种协议,比如SPI或者UART等标准时,速度更快,操作更加容易。 今天我就K64的普通GPIO实现软件SPI,来刷OLED。 GPIO涉及几个寄存器: 管脚控制寄存器: Pin Control Register n(PORTx_PCRn) 我们把管脚设为GPIO,我们只需设置MUX(10~8位)配置成GPIO模式即可,如手册的说明:
只要把MUX配置成001即可把你所选择的管脚设置位GPIO,如把PORTC5设置位GPIO模式的例子是:PORTC_PCR5 = PORT_PCR_MUX(1)| PORT_PCR_DSE_MASK; 还有值得提醒的是DSE位,这个位把IO口的驱动能力设置成驱动能力强模式,相对还有驱动能力弱模式,如手册的说明截图:
管脚数据输出寄存器:Port Data Direction Register (GPIOx_PDDR) 这个寄存器是把管脚的状态输出,把相应管脚的GPIOx_PDDR置一就是设置管脚位输出,否则就是设为输入,如把PORTC5设置为输出的例子:GPIOC_PDDR |= (1<<5); 手册上说明如下:
管脚置位输出寄存器:Port Set Output Register (GPIOx_PSOR) 这个寄存器是控制PDORn的值,而PDORn如果是1,在管脚设置为输出时,管脚就会输出高电平,否则低电平,如手册的关于PDORn的说明:
然后用户可以通过对GPIOx_PSOR寄存器写1就是把PDORn设为1,这样管脚就会输出高电平了(在管脚设置为输出时),还有注意的是,对GPIOx_PSOR写0是不会影响PDORn寄存器的值的,这点大家要注意,手册的说明如下:
管脚清零输出寄存器:Port Clear Output Register (GPIOx_PCOR) 这个寄存器跟上面的Port Set Output Register (GPIOx_PSOR)寄存器是一样的,用户对这个寄存器写1,就是把PDORn的值写为0,这样管脚就会输出低电平。同样要注意的是对这个寄存器写0是不会影响到PDORn的值的。手册的说明如下图: 现在我来讲解我的程序的流程吧。 首先是运行执行main函数之前,会进行系统时钟初始化这些操作,把时钟倍频到48M。 这部分我前面关于时钟这里有说明,大家可以参考那个帖子: 然后就是进行OLED的初始化,源代码如下: void LCD_Init(void) { OLED_GPIO_Init(); LCD_SCL_H; //LCD_CS=1; LCD_RST_L; LCD_DLY_ms(50); LCD_RST_H; Set_Display_On_Off(0x00); // Display Off (0x00/0x01) Set_Display_Clock(0x80); // Set Clock as 100 Frames/Sec Set_Multiplex_Ratio(0x3F); // 1/64 Duty (0x0F~0x3F) Set_Display_Offset(0x00); // Shift Mapping RAM Counter (0x00~0x3F) SetStartLine(0x00); // Set Mapping RAM Display Start Line(0x00~0x3F) Set_Charge_Pump(0x04); // Enable Embedded DC/DC Converter (0x00/0x04) SetAddressingMode(0x02); // Set Page Addressing Mode (0x00/0x01/0x02) Set_Segment_Remap(0x01); // Set SEG/Column Mapping 0x00???? 0x01?? Set_Common_Remap(0x08); // Set COM/Row Scan Direction 0x00???? 0x08?? Set_Common_Config(0x10); // Set Sequential Configuration (0x00/0x10) SetContrastControl(Brightness); //Set SEG Output Current Set_Precharge_Period(0xF1); // Set Pre-Charge as 15 Clocks& Discharge as 1 Clock Set_VCOMH(0x40); // Set VCOM Deselect Level Set_Entire_Display(0x00); // Disable Entire Display On (0x00/0x01) Set_Inverse_Display(0x00); // Disable Inverse Display On(0x00/0x01) Set_Display_On_Off(0x01); // Display On (0x00/0x01) LCD_Fill(0x00); //???? LCD_Set_Pos(0,0); } 前面是GPIO的初始化,后面是设置OLED的相关显示参数。 OLED管脚的初始化源代码: void OLED_GPIO_Init(void) { //把PORTC5,PORTC7,PORTC9,PORTC11设为GPIO PORTC_PCR5 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; PORTC_PCR7 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; PORTC_PCR9 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; PORTC_PCR11 =PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //把PORTC5,PORTC7,PORTC9,PORTC11管脚的方向设为输出 GPIOC_PDDR |= (1<<5); GPIOC_PDDR |= (1<<7); GPIOC_PDDR |= (1<<9); GPIOC_PDDR |= (1<<11); //把PORTC5,PORTC7,PORTC9,PORTC11的电平初始化为高电平 GPIOC_PSOR |= (1<<5); GPIOC_PSOR |= (1<<7); GPIOC_PSOR |= (1<<9); GPIOC_PSOR |= (1<<11); } 然后就是我的显示效果图:
|