我正在努力为MEMS加速度计的服务编制程序。我使用操纵杆E端口的三针(joy_left,joy_right,joy_down)来改变轴x、y和z。程序的最终目标是显示在4位数的7段显示器上:
表示轴(x,y,z)之一的
我在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 */目前,我遇到了以下问题:
mems_acc_read_xyz(&acc);User @atune正确地指出了这样一个事实:为加速值获取数据需要超过1ms,这与SysTick中断(每1ms称为中断)相冲突。对于我正在执行的任务,我不能向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)?有关吗?
谢谢你的所有答复。
发布于 2022-01-22 23:17:54
首先,您应该遍历代码,并考虑每一行所做的事情。也许首先考虑一下您想要代码做什么,并通过在代码中注释您的意图来记录它。
简单地看一下,在您的示例stm32l4xx_it.c中,首先是SysTick_Handler:
static int miliSec = 0;miliSec是一个有符号整数,它可以变成一个负值。如果您决定让它不断增加,直到溢出为止,请记住这一点。
将miliSec的其余部分除以4为digitOf4Sec。换句话说,digitOf4Sec只能是0、1、2或3。
digitOf4Sec = miliSec % 4;
// 0 % 4 = 0
// 1 % 4 = 1
// 2 % 4 = 2
// 3 % 4 = 3
// 4 % 4 = 0
// 5 % 4 = 1
// etc.然后使用digitOf4Sec,如果digitOf4Sec除以4为0,则只输入开关大小写。因为整数截断,所以它总是0。
// (digitOf4Sec CAN ONLY BE 0, 1, 2, or 3 like stated before)
// 0 / 4 = 0
// 1 / 4 = 0
// 2 / 4 = 0
// 3 / 4 = 0
if((digitOf4Sec / 4) == 0)
{
switch(digitOf4Sec)
{
// digitOf4Sec is always 0
case 0:
showDigit("axis");
...答案1)在交换机中的 ...so,除了0,您永远不能输入任何东西,因为'digitOf4Sec / 4‘总是0。这是什么意思“只有第一个数字是负责轴,没有其他数字超过这一点”?如果是的话,这就是你的答案。其他的案子是不可能的。
最后,您显然想每4秒清除计数器并每1000毫秒更新一次加速度值?
if(miliSec != 0)
{
if(miliSec / 1000 == 4)
miliSec = 0;
if(miliSec % 1000 == 0)
{
// x-y-z acceleration value update code
}
}
miliSec++;我不明白4秒的部分,但我想它运行得很好。
关于加速度计的值。我想你使用的是LSM303C电子罗盘的KAmeleon-STM32L4工具包。在main.c中,您将加速度计配置为2G全量程。加速度计有16位值,所以范围是-32768.32767,其中-32767是-2G,0是0G,+32767是+2G。换句话说,1 LSB是(1/32767G) ~= 0.000061G。
所以关于你的转换代码
x = acc.x * 2.0f / 32678.0f;
y = acc.y * 2.0f / 32678.0f;
z = acc.z * 2.0f / 32678.0f;答案2)--没关系,可能工作得很好,但您有一个错误。当然,32678应该是32768。而且,它很可能更像32767,但这不是什么大问题,一滴水。
将来,您可能需要考虑将所使用的值显式化。什么是2.0,什么是32768.0,它们为什么在那里?如果您决定将整个量程从2G更改为4G/8G,或者您想测试不同的范围,您总是想手动更改魔术数字吗?
哦,(不-)答案3)用操纵杆换轴也不起作用。这是你需要考虑自己的问题,你的代码不那么容易推理,特别是没有使用过的硬件和完整的图片。你需要调试你的代码,并反复检查你在做什么。顺便说一句,其实是操纵杆倒了PE2。你在看PE3,哪个在上面?
其他评论:
a)
void showDigit(const char * digitName)为什么只有4个有效值的c字符串-based参数?字符串不会从任何地方以明文形式出现。你应该用一个枚举代替。
( b)在inputHandling()中,当您到达延迟时,应该始终清除按钮,而不仅仅是当操纵杆按到某个方向时。
不管怎么说,这就是我的全部。有很多信息缺失,很难调试你的程序,仅仅通过视觉阅读。很大程度上是因为根本不清楚发生了什么和你想要发生什么。
https://stackoverflow.com/questions/70817096
复制相似问题