本帖最后由 gaoyang9992006 于 2021-8-13 16:10 编辑
#申请原创# @21小跑堂
--------------------------------------------------------------------
OLED是0.91寸的,IIC接口接口顺序为
GND VCC SCL SDA
经过观察,开发板的NU4接口可以为其供电,并提供IO功能,通过IO实现模拟IIC
如下图所示,7-10四个接口,VREF因为连接到了VDD,所以可以提供电能给OLED的VCC供电
又后面的IIC数据线跟OLED的相反,因此我们这里使用GPIO模拟实现
接下来移植oled的驱动
在main.c包含oled.h
在oled.h中粘贴:
#include "NuMicro.h"
结合上面选择的端口在oled.h中设置映射端口#define SCL_PORT (PC)
#define SCL_PIN (BIT0)
#define SDA_PORT (PC)
#define SDA_PIN (BIT1)
//-----------------OLED端口定义----------------
#define OLED_SCL_Clr() PC0=0
#define OLED_SCL_Set() PC0=1
#define OLED_SDA_Clr() PC1=0
#define OLED_SDA_Set() PC1=1
初始化GPIO为开漏
void oled_gpio_init(void)
{
GPIO_SetMode(SCL_PORT,SCL_PIN,GPIO_MODE_OPEN_DRAIN);
GPIO_SetMode(SDA_PORT,SDA_PIN,GPIO_MODE_OPEN_DRAIN);
CLK_SysTickDelay(1000);
}
另外发现如果时钟主频过高则导致OLED显示会出现异常,降低系统主频到51Mhz内即可解决
那个设置函数只能设置51MHz和120MHz。
main.c的内容为
#include "stdio.h"
#include "NuMicro.h"
#include "oled.h"
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable HIRC clock (Internal RC 48 MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Set core clock as 50MHz from PLL */
CLK_SetCoreClock(FREQ_50MHZ);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Select UART clock source from HIRC */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/*----------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*----------------------------------------------------------------------*/
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) |
(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Lock protected registers */
SYS_LockReg();
}
/*----------------------------------------------------------------------*/
/* Init UART0 */
/*----------------------------------------------------------------------*/
void UART0_Init(void)
{
/* Reset UART0 */
SYS_ResetModule(UART0_RST);
/* Configure UART0 and set UART0 baud rate */
UART_Open(UART0, 115200);
}
void led_init(void)
{
GPIO_SetMode(PB, BIT14, GPIO_MODE_OUTPUT);
PB14 = 1;
}
void led_blink(int i)
{
while(i--)
CLK_SysTickDelay(100000);
PB14 ^=1;
}
//初始化按键的端口为输入模式
void button_init(void)
{
GPIO_SetMode(PH, BIT4, GPIO_MODE_INPUT);
}
//通过按键改变一个数字从10到1的变化,用于控制LED闪烁的频率。
void get_button(int *i)
{
if(PH4==0)
{
CLK_SysTickDelay(1000);
if(PH4==0)
{
while(PH4==0);
(*i)--;
if(*i<=0) *i=10;
printf("i=%d T=%.2f s \n",*i,(float)*i/5);
}
}
}
void oled_gpio_init(void)
{
GPIO_SetMode(SCL_PORT,SCL_PIN,GPIO_MODE_OPEN_DRAIN);
GPIO_SetMode(SDA_PORT,SDA_PIN,GPIO_MODE_OPEN_DRAIN);
CLK_SysTickDelay(1000);
}
int32_t main(void)
{
int t=10;
int i=0;
/* Init System, IP clock and multi-function I/O. */
SYS_Init();
/* Init UART0 for printf */
UART0_Init();
printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);
printf("+-------------------------------------------------+\n");
printf("| PB.14(Output) and PCH.4(Input) Sample Code |\n");
printf("+-------------------------------------------------+\n\n");
led_init();
button_init();
oled_gpio_init();
OLED_Init();//初始化OLED
CLK_SysTickDelay(1000);
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
CLK_SysTickDelay(1000);
for(i=0;i<8;i++)
OLED_ShowChinese(i*16,0,i,16); //第一个是列坐标,字符是16×16,第二个是行开始的坐标,单位是8。第三个是写入第几个字符的数组编号
for(i=0;i<8;i++)
OLED_ShowChinese(i*16,2,i+8,16);
OLED_ShowString(0,2,"NuMaKer-471KI---",16);
while(1)
{
led_blink(t);
get_button(&t);
OLED_ShowNum(8*14,2,t,2,16);
}
}
该例程结合了我上一个GPIO输入输出和串口的例子,在原来的基础上增加实现了在OLED上显示文字,以及显示按键按下后,控制速度的变量。
01_OLED.rar
(14.97 KB)
|