【发布时间】:2022-01-22 20:59:37
【问题描述】:
我正在尝试为 MEMS 加速度计的服务制作程序。 我正在使用操纵杆端口 E 的三个引脚(joy_left、joy_right、joy_down)来改变轴 x、y 和 z。 该程序的最终目标是显示 4 位数字 7段显示器:
- 第一个数字代表轴 (x, y, z) 中的一个,使用范围从 1 到 3 的数字
- 倒数第二个数字必须代表其轴的加速度计值的三位数字
我在 main.c 中的代码:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2022 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"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "kamami_l496_mems.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void switchInit(void);
void baseTransistInit(void);
void segmentsInit();
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
HAL_PWREx_EnableVddIO2();
switchInit();
baseTransistInit();
segmentsInit();
mems_init(MEMS_ACC_DATARATE_10HZ, MEMS_ACC_FULLSCALE_2G);
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
SysTick_Config(SystemCoreClock / 1000); // SysTick_Handler() called within 1ms
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* 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
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void switchInit(void)
{
GPIO_InitTypeDef Joys;
Joys.Mode = GPIO_MODE_INPUT;
Joys.Pin = GPIO_PIN_1 /* JOY_LEFT */ | GPIO_PIN_0 /* JOY_RIGHT */ | GPIO_PIN_3 /* JOY_DOWN*/;
Joys.Pull = GPIO_PULLUP;
Joys.Speed = GPIO_SPEED_LOW;
Joys.Alternate = 0;
HAL_GPIO_Init(GPIOE, &Joys);
}
void baseTransistInit(void)
{
GPIO_InitTypeDef Transistors;
Transistors.Mode = GPIO_MODE_OUTPUT_PP;
Transistors.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
Transistors.Pull = GPIO_NOPULL;
Transistors.Speed = GPIO_SPEED_LOW;
Transistors.Alternate = 0;
HAL_GPIO_Init(GPIOB, &Transistors);
}
void segmentsInit()
{
GPIO_InitTypeDef Segments;
Segments.Mode = GPIO_MODE_OUTPUT_PP;
Segments.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_9;
Segments.Pull = GPIO_NOPULL;
Segments.Speed = GPIO_SPEED_LOW;
Segments.Alternate = 0;
HAL_GPIO_Init(GPIOG, &Segments);
}
/* 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 */
我正在尝试使用 SysTick 中断,因此我将在此处显示文件“stm32l4xx_it.c”中的代码:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32l4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2022 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 "stm32l4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "kamami_l496_mems.h"
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SEG_A 0
#define SEG_B 1
#define SEG_C 2
#define SEG_D 3
#define SEG_E 4
#define SEG_F 5
#define SEG_G 6
#define SEG_DP 9
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
int buttonMs = 0;
int buttonDelay = 500;
const uint16_t tableOfSegments[] = {
1 << SEG_A | 1 << SEG_B | 1 << SEG_C | 1 << SEG_D | 1 << SEG_E | 1 << SEG_F, // DIGIT 0
1 << SEG_B | 1 << SEG_C, // DIGIT 1
1 << SEG_A | 1 << SEG_B | 1 << SEG_E | 1 << SEG_D | 1 << SEG_G, // DIGIT 2
1 << SEG_A | 1 << SEG_B | 1 << SEG_C | 1 << SEG_D | 1 << SEG_G, // DIGIT 3
1 << SEG_B | 1 << SEG_C | 1 << SEG_G | 1 << SEG_F, // DIGIT 4
1 << SEG_A | 1 << SEG_F | 1 << SEG_G | 1 << SEG_C | 1 << SEG_D, // DIGIT 5
1 << SEG_A | 1 << SEG_F | 1 << SEG_G | 1 << SEG_C | 1 << SEG_D | 1 << SEG_E, // DIGIT 6
1 << SEG_A | 1 << SEG_B | 1 << SEG_C, // DIGIT 7
1 << SEG_A | 1 << SEG_B | 1 << SEG_C | 1 << SEG_D | 1 << SEG_E | 1 << SEG_F | 1 << SEG_G, // DIGIT 8
1 << SEG_A | 1 << SEG_B | 1 << SEG_C | 1 << SEG_D | 1 << SEG_F | 1 << SEG_G, // DIGIT 9
};
int showX = 1;
int showY = 0;
int showZ = 0;
float x, y, z;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
void inputHandling();
void makeDigitFromFloatValue(int pos, float input, int * digitToSet);
void showDigit(const char * digitName);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
struct mems_xyz_res acc; // structure for accelerometr results
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
static int miliSec = 0;
inputHandling();
int digitOf4Sec = miliSec % 4;
switch(digitOf4Sec)
{
case 0:
showDigit("axis");
break;
case 1: // digit 2
showDigit("first");
break;
case 2: // digit 3
showDigit("second");
break;
case 3: // digit 4
showDigit("third");
break;
}
if(miliSec != 0)
{
if(miliSec / 1000 == 4)
miliSec = 0;
if(miliSec % 1000 == 0)
{
x = acc.x * 2.0f / MEMS_ACC_MAXVAL;
y = acc.y * 2.0f / MEMS_ACC_MAXVAL;
z = acc.z * 2.0f / MEMS_ACC_MAXVAL;
}
}
mems_acc_read_xyz(&acc);
miliSec++;
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32L4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32l4xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
void inputHandling()
{
buttonMs++;
if(buttonMs < buttonDelay)
return;
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_0) == GPIO_PIN_RESET) // JOY RIGHT, Y
{
showX = 0;
showY = 1;
showZ = 0;
}
else if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_1) == GPIO_PIN_RESET) // JOY LEFT, X
{
showX = 1;
showY = 0;
showZ = 0;
}
else if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2) == GPIO_PIN_RESET) // JOY DOWN, Z
{
showX = 0;
showY = 0;
showZ = 1;
}
if(buttonMs == buttonDelay)
buttonMs = 0;
}
void makeDigitFromFloatValue(int pos, float input, int * digitToSet)
{
if(input < 0)
{
input *= -1;
}
int number = input * 100;
if(input < 10)
{
if(pos == 1)
*digitToSet = 0;
else if(pos == 2)
*digitToSet = 0;
else
*digitToSet = number % 10;
}
else if(input < 100)
{
if(pos == 1)
*digitToSet = 0;
else if(pos == 2)
{
number /= 10;
*digitToSet = number % 10;
}
else
*digitToSet = number % 10;
}
}
void showDigit(const char * digitName)
{
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_9, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5, GPIO_PIN_RESET);
if(strcmp(digitName, "axis") == 0)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
if(showX)
{
HAL_GPIO_WritePin(GPIOG, tableOfSegments[1], GPIO_PIN_SET);
}
else if(showY)
{
HAL_GPIO_WritePin(GPIOG, tableOfSegments[2], GPIO_PIN_SET);
}
else if(showZ)
{
HAL_GPIO_WritePin(GPIOG, tableOfSegments[3], GPIO_PIN_SET);
}
return;
}
int digitToShow;
if(strcmp(digitName, "first") == 0)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
makeDigitFromFloatValue(1, x, &digitToShow);
}
else if(strcmp(digitName, "second") == 0)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
makeDigitFromFloatValue(2, x, &digitToShow);
}
else if(strcmp(digitName, "third") == 0)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
makeDigitFromFloatValue(3, x, &digitToShow);
}
HAL_GPIO_WritePin(GPIOG, tableOfSegments[digitToShow], GPIO_PIN_SET);
}
/* USER CODE END 1 */
目前我遇到了以下问题:
- 只有第一个数字显示负责轴。除此之外没有其他数字。用操纵杆改变轴也不起作用。 我猜是因为 SysTickHandler 中断函数中的一行:
mems_acc_read_xyz(&acc);
用户@atune 正确指出了这样一个事实,即获取加速值的数据需要超过 1 毫秒的时间,并且与每 1 毫秒调用一次的 SysTick 中断发生冲突。对于我正在执行的任务,我无法向 main() 函数的无限循环添加任何内容,因此我只需要使用中断来完成它。 我搬家了:
mems_acc_read_xyz(&acc);
到 if,其中 x、y 和 z 用加速值初始化:
if(miliSec % 1000 == 0)
{
mems_acc_read_xyz(&acc);
x = floorf((acc.x * 2.0f / MEMS_ACC_MAXVAL) * 100) / 100; //acc.x * 2.0f / MEMS_ACC_MAXVAL;
y = floorf((acc.y * 2.0f / MEMS_ACC_MAXVAL) * 100) / 100; //acc.y * 2.0f / MEMS_ACC_MAXVAL;
z = floorf((acc.z * 2.0f / MEMS_ACC_MAXVAL) * 100) / 100; //acc.z * 2.0f / MEMS_ACC_MAXVAL;
}
现在显示轴的变化和加速值。但这些是正确的吗?当我移动板时,我得到每个轴的值,但仅从 0.00 到 0.09。我认为这里也有问题,最大范围应该更高?这个问题与我的功能有关吗makeDigitFromFloatValue(int pos, float input, int * digitToSet)?
提前感谢您的所有回答。
【问题讨论】:
-
问一些简单的具体问题。不要要求我们为您调试、解释器件数据表或编写程序。你的问题太笼统了:
uncertainty about getting correct acceleration values and showing it. Is my idea to do this correct or is it something I need to add / rebuild? Thank you in advance for all your answers投票结束
标签: c embedded accelerator