[ACM32G103RCT6 development board review] OLED multi-level menu based on tobudOS
[Copy link]
[Purpose of the experiment] Implementation of a multi-level menu based on tobudOS
【experiment equipment】
1. ACM32G103RCT6 development board
2. Rotary encoder
3. OLED screen
【Development board software】
1. MDK5.38
2. TobudOS
【Realize step gathering】
1. Copy a tobudOS project template
2. Transplant the OLED display driver. Copy the OLED driver library, create a new project grouped as OLED, and add the .c and .h files to the project.
3. Modify the initialization, write bytes, write commands, and write data of OLED. I use the hardware I2C driver here (the driver is not given in detail, and I wrote a 10,000 OLED driver). I saw this driver on Bilibili and shared it with you.
void I2C_Init(void)
{
I2C_Handle.Instance = I2C1;
I2C_Handle.Init.I2C_Mode = I2C_MODE_MASTER;
I2C_Handle.Init.Tx_Auto_En = TX_AUTO_ENABLE;
I2C_Handle.Init.Clock_Speed = CLOCK_SPEED_STANDARD;
I2C_Handle.Init.Stretch_Mode = STRETCH_MODE_DISABLE;
I2C_Handle.Init.filter_enable = FILTER_ALGO_DISABLE;
HAL_I2C_Init(&I2C_Handle);
}
/**
* 函 数:I2C发送一个字节
* 参 数:Byte 要发送的一个字节数据,范围:0x00~0xFF
* 返 回 值:无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
HAL_I2C_Master_Transmit(&I2C_Handle, 0x78, &Byte, 1, 100);
}
/**
* 函 数:OLED写命令
* 参 数:Command 要写入的命令值,范围:0x00~0xFF
* 返 回 值:无
*/
void OLED_WriteCommand(uint8_t Command)
{
int8_t buff[2];
buff[0] = 0x00;
buff[1] = Command;
HAL_I2C_Master_Transmit(&I2C_Handle, 0x78, buff, 2, 100);
}
/**
* 函 数:OLED写数据
* 参 数:Data 要写入数据的起始地址
* 参 数:Count 要写入数据的数量
* 返 回 值:无
*/
void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
uint8_t i;
int8_t buff[Count+1];
buff[0] = 0x40;
for(i = 1; i<Count; i++)
{
buff[i] = Data[i];
}
HAL_I2C_Master_Transmit(&I2C_Handle, 0x78, buff, Count+1, 100);
}
4. Key drive. There is a key on the rotary encoder. I connected it to the onboard key PC13. The code is as follows:
int8_t Key_Enter_Get(void)
{
if(Key_Enter)
{
Key_Enter = 0;
return 1;
}
return 0;
}
void HAL_EXTI_LineCallback(uint32_t Line)
{
if (Line == BSP_PB_PIN)
{
BSP_LED_Toggle();
Key_Enter += 1;
}
}
5. The encoder driver is described in detail in the post: [ACM32G103RCT6 Development Board Evaluation] TobudOS implements the initial test of multi-task encoder - Domestic chip exchange - Electronic Engineering World Forum (eeworld.com.cn) , so I will not go into details. The code is as follows:
#include "main.h" // Device header
TIM_HandleTypeDef TIM15_Handler; // PA2 and PA3
/************************************************************************
* function : TIM6_IRQHandler
* Description: TIM6 Interrupt Handler
************************************************************************/
void TIM15_IRQHandler(void)
{
if (TIM15->SR & TIMER_SR_UIF)
{
}
TIM15->SR = 0; //write 0 to clear hardware flag
}
void TIM15_MSP_Pre_Init(TIM_HandleTypeDef * htim)
{
HAL_TIMER_MSP_Init(&TIM15_Handler);
}
void TIM15_MSP_Post_Init(void)
{
GPIO_InitTypeDef gpio_init;
__HAL_RCC_GPIOC_CLK_ENABLE();
gpio_init.Pin = GPIO_PIN_1 | GPIO_PIN_2; //TIM15_CH1 and TIM15_CH2
gpio_init.Mode = GPIO_MODE_AF_PP;
gpio_init.Pull = GPIO_PULLUP;
gpio_init.Alternate = GPIO_FUNCTION_1;
gpio_init.Drive = GPIO_DRIVE_LEVEL3;
HAL_GPIO_Init(GPIOC, &gpio_init);
}
void TIM15_Init(void)
{
uint32_t timer_clock;
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
timer_clock = HAL_RCC_GetPCLK2Freq();
if (HAL_RCC_GetHCLKFreq() != timer_clock ) // if hclk/pclk != 1, then timer clk = pclk * 2
{
timer_clock = timer_clock << 1;
}
TIM15_Handler.Instance = TIM15;
TIM15_Handler.Init.ARRPreLoadEn = TIM_ARR_PRELOAD_ENABLE;
TIM15_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TIM15_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
TIM15_Handler.Init.RepetitionCounter = 0;
TIM15_Handler.Init.Prescaler = 0;
TIM15_Handler.Init.Period = 0xFFFF;
TIM15_MSP_Pre_Init(&TIM15_Handler);
HAL_TIMER_Base_Init(&TIM15_Handler);
HAL_TIM_ENABLE_IT(&TIM15_Handler, TIMER_INT_EN_UPD);
TIM15_MSP_Post_Init();
sSlaveConfig.SlaveMode = TIM_SLAVE_MODE_ENC1;
sSlaveConfig.InputTrigger = TIM_TRIGGER_SOURCE_TI1FP1;
sSlaveConfig.TriggerPolarity = TIM_SLAVE_CAPTURE_ACTIVE_RISING;
sSlaveConfig.TriggerFilter = TIM_TI1_FILTER_LVL(0); // no filter
HAL_TIMER_Slave_Mode_Config(&TIM15_Handler, &sSlaveConfig);
}
int16_t Read_Encoder(void)
{
int16_t Encoder_TIM;
Encoder_TIM = (int16_t) TIM15->CNT-65536;
TIM15->CNT = 65536;
return Encoder_TIM;
}
void Encoder_Init(void)
{
TIM15_Init();
HAL_TIMER_Base_Start(TIM15_Handler.Instance);
}
int16_t Encoder_Get(void)
{
// /*原样输出*/
// int16_t temp;
// temp = TIM_GetCounter(TIM1);
// TIM_SetCounter(TIM1, 0);
// return temp;
/*除以4输出*/
int16_t temp;
temp = (TIM15->CNT+2)/2;
if(temp)
{
TIM15->CNT = TIM15->CNT-(temp*2);
return temp;
}
return 0;
}
void Encoder_Reset(void)
{
TIM15->CNT = 0;
}
5. Migrate the menu. Find the open source code on the Internet and copy the menu to the project.
6. Schedule main_menu in a task to achieve the menu effect.
Video effects:
OLED多级菜单
|