注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
lugl4313820的个人空间 https://home.eeworld.com.cn/space-uid-1269709.html [收藏] [复制] [分享] [RSS]
日志

【ACM32G103RCT6开发板测评】基于tobudOS的OLED多级菜单

已有 212 次阅读2024-1-11 12:07

【实验目的】基于tobudOS的多级菜单的实现

【实验器材】

1、ACM32G103RCT6开发板

2、旋转编码器

3、OLED屏

【开发板软件】

1、MDK5.38

2、TobudOS

【实现步聚】

1、复制一个我的tobudOS工程模板

2、移植OLED显示驱动。复制OLED驱动库,新建工程分组OLED,并把.c与.h添加进工程。

 

3、修改OLED的初始化、写字节、写命令、写数据,我这里使用硬件I2C驱动(驱动不详细给出了呀,写了一万的OLED驱动了)。这个驱动我是在B站上看到大佬的,分享过来。

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、按键驱动,旋转编码器上有一个按建,我这里接到了板载的按键PC13上面,代码如下:

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、编码器的驱动,在帖子:【ACM32G103RCT6开发板测评】tobudOS实现多任务编码器的初试 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)已经详细说明了驱动,所以不再多述,其代码如下:

#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、菜单的移植,在网上找到开源代码,复制menu到工程

 

6、开在一个任务中调度main_menu,就可以实现菜单的效果。

 

视频效果:

OLED多级菜单

 

本文来自论坛,点击查看完整帖子内容。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章