u8g2实现文字移动(按键)——基于STM32F407、硬件SPI

u8g2实现文字移动——基于STM32F407、硬件SPI

感谢小蛋显璐的教程:硬核! OLED丝滑菜单教程

  • 实现按键上下移动,效果如下:
    滚动菜单

  • 端口配置如下:

端口配置1
端口配置2

  • main.c
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "spi.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "u8g2.h"
#include "oled_driver.h"
#include "stdio.h"
#include "math.h"

#include "KUNKUN.h"
#include "Jinitaimei.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct
{
    char *str;
    uint8_t len;
} SETTING_LIST;
typedef struct
{
    uint8_t val;
    uint8_t last_val;
} KEY_T;
typedef struct
{
    uint8_t id;
    uint8_t press;
    uint8_t update_flag;
    uint8_t res;
} KEY_MSG;



/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
u8g2_t u8g2;

#define KEY0() HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)
#define KEY1() HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
short x, x_trg, y = 10, y_trg = 10; //x当前位置数值,x_trg 目标坐标值
short frame_len, frame_len_trg, frame_y, frame_y_trg; //框的宽高
char ui_select = 0;
int state;

KEY_T key[2] = {0};
KEY_MSG key_msg = {0};
SETTING_LIST list[] =
{
    {"list_a"},
    {"list_b"},
    {"list_c"},
    {"list_1"},
    {"list_2"},
    {"list_3"},
    {"list_4"},
    {"list_5"},
    {"list_6"},
};
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void PrintVarFormat(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const uint8_t *font, short var)
{
    char var_buff[100];
    u8g2_SetFont(u8g2, font);
    sprintf(var_buff, "%4d", var);
    u8g2_DrawStr(u8g2, x, y, var_buff);
}

uint8_t get_io_val(uint8_t ch)//获取两个按键的状态(这里是初始化拉高,低电平按下)
{
    if(ch == 0)
    {
        return KEY0();
    }
    else
    {
        return KEY1();
    }
}
void key_init(void)
{
    for(int i = 0; i < 2; i++)
    {
        key[i].val = key[i].last_val = get_io_val(i);
    }
}
void key_scan(void)
{
    for(int i = 0; i < 2; i++)
    {
        key[i].val =  get_io_val(i);//扫描两个键的状态,这里是按下为0
        if(key[i].val != key[i].last_val)//电平变化说明按下
        {
            key[i].last_val = key[i].val;//让电平标志位相同,只记录一次
            if(key[i].val == 0)//按下
            {
                key_msg.id = i;//记录哪个按键
                key_msg.press = 1;//按下
                key_msg.update_flag = 1;//更新
            }
        }
    }
}
int ui_run(short *a, short *a_trg)
{
    if(*a < *a_trg)
    {
        *a += 1;
    }
    else if( *a > *a_trg)
    {
        *a -= 1;
    }
    else
    {
        return 0;
    }
    return 1;
}


void ui_show(void)
{
    int list_len = sizeof(list) / sizeof(SETTING_LIST);
    u8g2_ClearBuffer(&u8g2);         // 清除内部缓冲区
    for(int i = 0 ; i < list_len; i++)
    {
        u8g2_DrawStr(&u8g2, x + 2, y + i * 10, list[i].str); // 第一段输出位置
    }
    ui_run(&y, &y_trg);
    //    u8g2_DrawRFrame(&u8g2, x, frame_y, frame_len, 22, 3);
    //    ui_run(&frame_y, &frame_y_trg, 5, 4);
    //    ui_run(&frame_len, &frame_len_trg, 10, 5);
    u8g2_SendBuffer(&u8g2);          // transfer internal memory to the displa
}
void ui_proc(void)
{
    //    int list_len = sizeof(list) / sizeof(SETTING_LIST);

    if(key_msg.update_flag && key_msg.press)
    {
        key_msg.update_flag = 0;
        if(key_msg.id)
        {
            y_trg += 10;
            //            ui_select++;
            //            if(ui_select >= list_len)
            //            {
            //                ui_select = list_len - 1;
            //            }
        }
        else
        {
            y_trg -= 10;
            //            ui_select--;
            //            if(ui_select < 0)
            //            {
            //                ui_select = 0;
            //            }
        }
        //        frame_y_trg = ui_select * 20;
        //        frame_len_trg = list[ui_select].len * 13;
    }
    ui_show();
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_SPI1_Init();

    /* Initialize interrupts */
    MX_NVIC_Init();
    /* USER CODE BEGIN 2 */
    MD_OLED_RST_Set();
    key_init();
    u8g2Init(&u8g2);
    //    u8g2_SetFont(&u8g2, u8g2_font_t0_22_mf );
    u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr );
    //    frame_len = frame_len_trg = list[ui_select].len * 13;
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        key_scan();
        ui_proc();
    }
    /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /** Initializes the RCC Oscillators according to the specified parameters
    * in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 8;
    RCC_OscInitStruct.PLL.PLLN = 336;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 4;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
    {
        Error_Handler();
    }
}

/**
  * @brief NVIC Configuration.
  * @retval None
  */
static void MX_NVIC_Init(void)
{
    /* DMA2_Stream3_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */
    __disable_irq();
    while (1)
    {
    }
    /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深藏ぺblue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值