这段时间一直在忙,所以就晚上自己加加班搞搞这块L476RG的板子,说出来都是泪,首先自己装的STM32CubeMX老是闪退,自己准备用TIM进行捕捉解红外码,调试2个周末加3个晚上终于搞定了,ST推出的库一开始用感觉真不方便,很多地方多不懂。自己就这样硬着头皮慢慢啃了,后来在论坛上发现版主netlhx的《NUCLEO教程》真是新手的指路灯,再次感谢netlhx版主的资料分享。
我这次做的是用红外遥控可以使液晶显示多个画面,字库自己做的,可以用红外修改参数的数值并保存,有些比较重要的画面还有要求输入密码,只有密码正确才能进入,废话不多说了,看图吧。
添加一些代码,我觉得注释还是蛮多的,详情见附件源码。- //-------------------------------------
- //
- // 具体菜单选项定义,定义一个结构数组
- // 存储在编码区,节省内存RAM
- //
- //-------------------------------------
- struct Option sOption[OPTIONMETE] = {
- {0,4,13, "基本设置 ",4}, //0
- {0,18,13,"反馈设置 ",4}, //1
- {0,46,13,"高级设置 ",4}, //2
- {0,73,13,"故障诊断 ",4}, //3
- {1,OPTIONMETE-1,0," ",0}, //4
- {1,OPTIONMETE-1,0," 请输入基本密码",0}, //5
- {1,OPTIONMETE-1,0," ",0}, //6
- {1,OPTIONMETE-1,0," ",0}, //7
- {2,OPTIONMETE-1,0,"关位确认 ",4}, //8
- {2,OPTIONMETE-1,0,"开位确认 ",4}, //9
- {2,OPTIONMETE-1,0,"调节死区 ",4}, //10
- {2,OPTIONMETE-1,0,"丢信动作 ",4}, //11
- {2,OPTIONMETE-1,0,"关过矩值 ",4}, //12
- {2,OPTIONMETE-1,0,"开过矩值 ",4}, //13
- {2,OPTIONMETE-1,0,"显示方向 ",4}, //14
- {2,OPTIONMETE-1,0,"现场控制 ",4}, //15
- {2,OPTIONMETE-1,0,"更改基本密码 ",6}, //16
- {2,OPTIONMETE-1,0,"恢复出厂值 ",5}, //17
- {3,OPTIONMETE-1,1," ",0}, //18
- {3,OPTIONMETE-1,1," 请输入反馈密码",0}, //19
- {3,OPTIONMETE-1,1," ",0}, //20
- {3,OPTIONMETE-1,1," ",0}, //21
- {4,OPTIONMETE-1,1,"低端微调 ",4}, //22
- {4,OPTIONMETE-1,1,"高端微调 ",4}, //23
- {4,27,1,"触点输出 ",4}, //24
- {4,27,1,"扩展触点 ",4}, //25
- {4,OPTIONMETE-1,1,"更改反馈密码 ",6}, //26
- {5,OPTIONMETE-1,24,"关到位 ",3}, //27
- {5,OPTIONMETE-1,24,"开到位 ",3}, //28
- {5,OPTIONMETE-1,24,"关过矩 ",3}, //29
- {5,OPTIONMETE-1,24,"开过矩 ",3}, //30
- {5,OPTIONMETE-1,24,"过 矩 ",3}, //31
- {5,OPTIONMETE-1,24,"正在关 ",3}, //32
- {5,OPTIONMETE-1,24,"正在开 ",3}, //33
- {5,OPTIONMETE-1,24,"正在运行 ",4}, //34
- {5,39,24,"中间位置 ",4}, //35
- {5,OPTIONMETE-1,24,"远方位置 ",4}, //36
- {5,OPTIONMETE-1,24,"现场位置 ",4}, //37
- {6,OPTIONMETE-1,35," 运行到达位置 ",0}, //38
- {6,OPTIONMETE-1,35," ",0}, //39
- {6,OPTIONMETE-1,35," ",0}, //40
- {6,OPTIONMETE-1,35," ",0}, //41
- {7,OPTIONMETE-1,24," 故障报警 ",0}, //42
- {7,OPTIONMETE-1,24,"过矩报警 ",4}, //43
- {7,OPTIONMETE-1,24,"远方报警 ",4}, //44
- {7,OPTIONMETE-1,24," ",0}, //45
- {8,OPTIONMETE-1,2," ",0}, //46
- {8,OPTIONMETE-1,2," 请输入高级密码",0}, //47
- {8,OPTIONMETE-1,2," ",0}, //48
- {8,OPTIONMETE-1,2," ",0}, //49
- {9,OPTIONMETE-1,2,"ESD 设置 ",4}, //50
- {9,OPTIONMETE-1,2,"关闭方式 ",4}, //51
- {9,OPTIONMETE-1,2,"关闭方向 ",4}, //52
- {9,OPTIONMETE-1,2,"正反作用 ",4}, //53
- {9,OPTIONMETE-1,2,"转矩显示 ",4}, //54
- {9,OPTIONMETE-1,2,"反馈低端 ",4}, //55
- {9,OPTIONMETE-1,2,"两线控制 ",4}, //56
- {9,OPTIONMETE-1,2,"标定低信 ",4}, //57
- {9,OPTIONMETE-1,2,"标定高信 ",4}, //58
- {9,OPTIONMETE-1,2,"刹车制动 ",4}, //59
- {9,OPTIONMETE-1,2,"停动时间 ",4}, //60
- {9,OPTIONMETE-1,2,"间断运行 ",4}, //61
- {9,OPTIONMETE-1,2,"更改高级密码 ",6}, //62
- {9,OPTIONMETE-1,2,"基本密码查询 ",6}, //63
- {9,OPTIONMETE-1,2,"反馈密码查询 ",6}, //64
- {9,66,2,"保存出厂值 ",5}, //65
- {10,OPTIONMETE-1,65," ",0}, //66
- {10,OPTIONMETE-1,65,"请输入出厂密码 ",0}, //67
- {10,OPTIONMETE-1,65," ",0}, //68
- {10,OPTIONMETE-1,65," ",0}, //69
- {11,OPTIONMETE-1,65,"保存出厂设置 ",6}, //70
- {11,OPTIONMETE-1,65,"电源选项 ",4}, //71
- {11,OPTIONMETE-1,65,"远方保持 ",4}, //72
- {12,OPTIONMETE-1,3,"方式钮位置 ",5}, //73
- {12,OPTIONMETE-1,3,"操作钮位置 ",5}, //74
- {12,OPTIONMETE-1,3,"远方打开信号 ",6}, //75
- {12,OPTIONMETE-1,3,"远方关闭信号 ",6}, //76
- {12,OPTIONMETE-1,3,"远方保持信号 ",6}, //77
- {12,OPTIONMETE-1,3,"远方自动信号 ",6}, //78
- {12,OPTIONMETE-1,3,"远方ESD 信号 ",6}, //79
- {12,OPTIONMETE-1,3,"控制电流 ",4}, //80
- {13,OPTIONMETE-1,61,"开向始位 ",4}, //81
- {13,OPTIONMETE-1,61,"开向终位 ",4}, //82
- {13,OPTIONMETE-1,61,"开向动程 ",4}, //83
- {13,OPTIONMETE-1,61,"开向停时 ",4}, //84
- {13,OPTIONMETE-1,61,"关向始位 ",4}, //85
- {13,OPTIONMETE-1,61,"关向终位 ",4}, //86
- {13,OPTIONMETE-1,61,"关向动程 ",4}, //87
- {13,OPTIONMETE-1,61,"关向停时 ",4}, //88
- {14,OPTIONMETE-1,50,"ESD 动位 ",4}, //89
- {14,OPTIONMETE-1,50,"ESD 有效电平 ",6}, //90
- {14,OPTIONMETE-1,50,"ESD 超越过热 ",6}, //91
- {14,OPTIONMETE-1,50,"ESD 超越停止 ",6}, //92
- {14,OPTIONMETE-1,50,"ESD 超越间断 ",6}, //93
- {14,OPTIONMETE-1,50,"ESD 超越过矩 ",6}, //94
- {15,OPTIONMETE-1,56," 两线设置 ",0}, //95
- {15,OPTIONMETE-1,56,"有信开,无信关 ",7}, //96
- {15,OPTIONMETE-1,56,"有信关,无信开 ",7}, //97
- {MENULEVEL-1,OPTIONMETE-1,0,"",0} //98
- };
- //----------------------------------------
- //
- // 菜单上移一项函数
- // 函数原形:void MenuUpOneOption (void);
- // 没有参数,没有返回值
- // 调用方式:void MenuUpOneOption (void);
- //
- //----------------------------------------
- void MenuUpOneOption (void)
- {
- if(MenuLevelStart()) //如果当前为表单第一项
- {
- if(Level[sOption[SelectIndex].KeyLevel][2]>=4) //并且表单中选项数目大于等于4个
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1]-3; //第一行显示索引号为倒数第四项
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为表单最后一项
- SelectLine = 4; //标记选择行为第四行
- DIS12864M(); //刷新屏幕显示
- }
- else //如果选项数目并不大于四个
- {
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为当前表单最后一个
- SelectLine = Level[sOption[SelectIndex].KeyLevel][2]; //显示行表单数目(最后一个)
- DIS12864M(); //刷新屏幕显示
- }
- }
- else //如果当前不是开始索引
- {
- if(SelectLine==1) //并且已经在屏幕最上边一行
- {
- FirstLineDisIndex--; //显示索引上移
- SelectIndex--; //选择索引自减
- SelectLine = 1; //选择行还是第一行
- DIS12864M (); //刷新屏幕
- }
- else //如果不是第一行
- {
- SelectLine--; //选择行自减
- SelectIndex--; //选择索引自减
- DIS12864M (); //刷新屏幕显示
- }
- }
- }
- //----------------------------------------
- //
- // 菜单下移一项函数
- // 函数原形:void MenuDownOneOption (void);
- // 没有参数,没有返回值
- // 调用方式:void MenuDownOneOption (void);
- //
- //----------------------------------------
- void MenuDownOneOption (void)
- {
- if(MenuLevelEnd()) //如果当前是表单最后一个索引
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一个选项
- SelectIndex = Level[sOption[SelectIndex].KeyLevel][0]; //选择索引为表单第一个选项索引
- SelectLine = 1; //选择行为第一行
- DIS12864M (); //刷新显示
- }
- else //如果不是最后的索引
- {
- if(SelectLine!=4) //如果当前不是屏幕最底行
- {
- SelectIndex++; //选择索引自加
- SelectLine++; //选择行下移
- // SetALineReverse (SelectLine); //刷新选择行
- DIS12864M (); //刷新显示
- }
- else //如果是屏幕最低行
- {
- FirstLineDisIndex++; //第一行显示下移
- SelectIndex++; //选择索引自加
- DIS12864M(); //刷新显示
- }
- }
- }
- //----------------------------------------
- //
- // 菜单退出功能函数
- // 函数原形:void MenuCancelOption (void);
- // 没有参数,没有返回值
- // 调用方式:void MenuCancelOption (void);
- //
- //----------------------------------------
- void MenuCancelOption (void)
- {
- if(SelectIndex != OPTIONMETE-1) //如果不是从功能返回
- {
- if(CancelIndex_flag == 1 && sOption[SelectIndex].KeyLevel == 5) { CancelIndex_flag = 0; SelectIndex = 25;}
- else
- SelectIndex = sOption[SelectIndex].CancelIndex; //选择索引为选项返回索引
- }
- else //如果是从功能返回
- SelectIndex = LastIndex;//索引等于进入前保存索引
- if(Level[sOption[SelectIndex].KeyLevel][2]>=4) //如果返回表单选项数目大于4个
- {
- if(SelectIndex > Level[sOption[SelectIndex].KeyLevel][1]-3) //根据返回选项确定显示首项
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1]-3;
- SelectLine = 4-(Level[sOption[SelectIndex].KeyLevel][1]-SelectIndex);
- DIS12864M (); //刷新显示
- }
- else //一般显示方式
- {
- FirstLineDisIndex = SelectIndex; //第一行显示索引
- SelectLine = 1; //选择第一行
- DIS12864M (); //刷新菜单
- }
- }
- else //如果返回表单选项数目不足4个
- {
- FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示索引为表单第一项
- SelectLine = SelectIndex - Level[sOption[SelectIndex].KeyLevel][0]+1; //选择行标志为当前选择索引对应行
- DIS12864M (); //刷新菜单
- }
- }
复制代码 因为之前的文件比较大,我就上传了源代码(未添加L4的库),现在我已经将整个开发工程上传到百度云(可直接编译)。
链接:游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0
main.c文件:
- /**
- ******************************************************************************
- * @file TIM/TIM_InputCapture/Src/main.c
- * @author MCD Application Team
- * @version V1.1.0
- * @date 16-September-2015
- * @brief This example shows how to use the TIM peripheral to measure only
- * the frequency of an external signal.
- ******************************************************************************
- * @attention
- *
- * [b]© COPYRIGHT(c) 2015 STMicroelectronics[/b]
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- #include "public.h"
- #include "lcd12864_st7567.h"
- #include "sys_time.h"
- #include "HS0038.h"
- /** @addtogroup STM32L4xx_HAL_Examples
- * @{
- */
- /** @addtogroup TIM_InputCapture
- * @{
- */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Captured Values */
- uint32_t uwIC2Value1 = 0;
- uint32_t uwIC2Value2 = 0;
- uint32_t uwDiffCapture = 0;
- /* Capture index */
- uint16_t uhCaptureIndex = 0;
- /* Frequency Value */
- uint32_t uwFrequency = 0;
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- void Error_Handler(void);
- static void MX_GPIO_Init(void);
- extern void MenuReflash(void);
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief Main program
- * @param None
- * @retval None
- */
- int main(void)
- {
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* Configure the system clock to 72 MHz */
- SystemClock_Config();
- /* Configure LED2 */
- BSP_LED_Init(LED2);
-
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
-
- /* 延时函数初始化 */
- Delay_init(72);
-
- /* 红外初始化 */
- HS0038_init();
- /* LCD初始化 */
- ST7567_Init();
-
- /* 初始化界面 */
- running_interface();
- while (1)
- {
- if(IR_OK_flag) //红外控制
- {
- IR_OK_flag = 0;
- MenuReflash();
- }
- BSP_LED_Toggle(LED2);
- Delay_ms(200);
- }
- }
- /**
- * @brief Conversion complete callback in non blocking mode
- * @param htim : hadc handle
- * @retval None
- */
- uint8_t IR_value_old = 0;
- uint8_t IR_value[4]={0};
- uint8_t IR_OK_flag = 0;
- uint16_t tim_value=0;
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
- {
- static uint8_t sta_flag = 0,i=0,num=0;
- static uint16_t IR_time[33]={0};
-
- tim_value = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
-
- if( tim_value >= 1200 && tim_value<= 1500 ) //寄一个数0.01ms
- { sta_flag = 1; }
- if(sta_flag)
- {
- if( i <= 8 ) num = 0;
- else if( i <= 16 ) num = 1;
- else if( i <= 24 ) num = 2;
- else if( i <= 32 ) num = 3;
-
- IR_value[num] <<= 1;
-
- if( tim_value >160 )
- {
- IR_value[num] |= 0x01;
- }
- else
- {
- IR_value[num] &= 0xfe;
- }
-
- IR_time[i++] = tim_value;
-
- IR_value_old = 0;
- if(i>=33)
- {
- i=0;
- sta_flag =0;
- if(IR_value[0]==Judgment_value)
- {
- IR_OK_flag = 1;
- IR_value_old = IR_value[3];
- }
- else
- {
- IR_value[0]=0;
- IR_value[1]=0;
- IR_value[2]=0;
- IR_value[3]=0;
- }
- }
- }
- TIM1->CNT = 0;
- }
- /**
- * @brief System Clock Configuration
- * The system Clock is configured as follows :
- * System Clock source = PLL (MSI)
- * SYSCLK(Hz) = 72000000
- * HCLK(Hz) = 72000000
- * AHB Prescaler = 1
- * APB1 Prescaler = 1
- * APB2 Prescaler = 1
- * HSI Frequency(Hz) = 16000000
- * PLL_M = 2
- * PLL_N = 18
- * PLL_R = 2
- * PLL_P = 7
- * PLL_Q = 2
- * Flash Latency(WS) = 4
- * @param None
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = 16;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
- RCC_OscInitStruct.PLL.PLLM = 2;
- RCC_OscInitStruct.PLL.PLLN = 18;
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
- RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
- RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- 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_DIV1;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
- __PWR_CLK_ENABLE();
- HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
- HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
- /* SysTick_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
- }
- /** Configure pins as
- * Analog
- * Input
- * Output
- * EVENT_OUT
- * EXTI
- */
- void MX_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- /* GPIO Ports Clock Enable */
- __GPIOH_CLK_ENABLE();
- __GPIOC_CLK_ENABLE();
- __GPIOA_CLK_ENABLE();
- __GPIOB_CLK_ENABLE();
- /*Configure GPIO pins : PC5 PC6 PC8 PC11 */
- GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_11;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
- /*Configure GPIO pin : PA12 */
- GPIO_InitStruct.Pin = GPIO_PIN_12;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- /**
- * @brief This function is executed in case of error occurrence.
- * @param None
- * @retval None
- */
- void Error_Handler(void)
- {
- /* Turn LED2 on */
- BSP_LED_On(LED2);
- while (1)
- {
- }
- }
- #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 can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d", file, line) */
- /* Infinite loop */
- while (1)
- {
- }
- }
- #endif
- /**
- * @}
- */
- /**
- * @}
- */
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码
|