查看: 1719|回复: 2

[分享] 【MCX-N947分享】+ 驱动摇杆

[复制链接]
  • TA的每日心情
    开心
    昨天 14:34
  • 签到天数: 1100 天

    连续签到: 18 天

    [LV.10]以坛为家III

    28

    主题

    4267

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5778
    最后登录
    2025-7-26
    发表于 2024-3-30 14:16:55 | 显示全部楼层 |阅读模式
    本帖最后由 suncat0504 于 2024-3-30 14:28 编辑

    我使用的是双轴按键摇杆传感器,
    摇杆.png
    感觉上就是两个可调电阻加上一个按键。因此使用MCX-N947开发板上的ADC功能就可以了。按照这个想法,根据板子的设计,准备使用P4_23和P4_15这两个GPIO作为ADC端口用,这两个口在可以从J1的70号和62号引出来。
    摇杆1.png 摇杆0.png


    初始化ADC功能,要使用对应的时钟总线,开放复用功能,和ADC通道等。ADC内置多个命令缓冲器,为不同的通道扫描和独立通道选择提供灵活性 触发源。这些命令缓冲器可配置用于: 单端转换。向SWTRIG写入1,可以以软件方式启动ADC转换。如果一次想要完成2个通道的转换,需要进行类似下面的设置:
    mLpadcCommandConfigStruct_x.enableAutoChannelIncrement = true;
    mLpadcCommandConfigStruct_x.loopCount = 1;
    第一条指令是允许自动调整通道号加1,第二个指令是表示连续采集几个通道。假如读取的第一个通道是 channel0,那么loopCount=1,就会读取channel0-1,一共2个通道的数据。
    ADC转换每次只会返回一个数据,如果连续采集多个通道的话,因为每次都读回来的数据,都会带着 commandIdSource 和 loopCountIndex,也就是前面说到的几号指令,和循环读取的次数。
    这样我们就能知道是sideA或B,第几个通道的数据了
    原理上是这样,但是程序上面没有调通。在发出开始转换指令后,无法取得第二个数据。所以我就系采用本办法,每次转换一个通道,转换完,在转换下一个通道。这样终于可以同时获得摇杆两个方向上的ADC结果了。

    主程序代码如下:
    1. /*

    2. * Copyright 2019 NXP

    3. * All rights reserved.

    4. *

    5. * SPDX-License-Identifier: BSD-3-Clause

    6. */



    7. #include "fsl_debug_console.h"

    8. #include "pin_mux.h"

    9. #include "clock_config.h"

    10. #include "board.h"

    11. #include "fsl_lpadc.h"

    12. #include "fsl_common.h"

    13. #include "stdio.h"

    14. #include "oled.h"





    15. /*******************************************************************************

    16. * Definitions

    17. ******************************************************************************/

    18. #define BOARD_LED_GPIO     BOARD_LED_RED_GPIO

    19. #define BOARD_LED_GPIO_PIN BOARD_LED_RED_GPIO_PIN



    20. #define DEMO_LPADC_BASE         ADC0

    21. #define DEMO_LPADC_USER_CHANNEL_X 2U

    22. #define DEMO_LPADC_USER_CHANNEL_Y 1U

    23. #define DEMO_LPADC_USER_CMDID   1U

    24. /* Use VREF_OUT driven from the VREF block as the reference volatage */

    25. #define DEMO_LPADC_VREF_SOURCE           kLPADC_ReferenceVoltageAlt3

    26. #define DEMO_LPADC_DO_OFFSET_CALIBRATION true

    27. #define DEMO_LPADC_OFFSET_VALUE_A        0x10U

    28. #define DEMO_LPADC_OFFSET_VALUE_B        0x10U



    29. #define DEMO_VREF_BASE VREF0



    30. uint32_t exec_adc_y(void);

    31. uint32_t exec_adc_x(void);



    32. /*******************************************************************************

    33. * Prototypes

    34. ******************************************************************************/

    35. void BOARD_InitDebugConsole(void);



    36. const uint32_t g_LpadcFullRange   = 4096U;

    37. const uint32_t g_LpadcResultShift = 3U;



    38. lpadc_conv_result_t mLpadcResultConfigStruct;



    39. /*******************************************************************************

    40. * Prototypes

    41. ******************************************************************************/



    42. /*******************************************************************************

    43. * Variables

    44. ******************************************************************************/

    45. volatile uint32_t g_systickCounter;



    46. /*******************************************************************************

    47. * Code

    48. ******************************************************************************/

    49. void SysTick_Handler(void) {

    50.     if (g_systickCounter != 0U) {

    51.         g_systickCounter--;

    52.     }

    53. }





    54. void SysTick_DelayTicks(uint32_t n) {

    55.     g_systickCounter = n;

    56.     while (g_systickCounter != 0U) {

    57.         

    58.     }

    59. }





    60. /*!

    61. * @brief Main function

    62. */

    63. int main(void) {

    64.     uint8_t ch;

    65.     uint32_t adcValue = 0U;

    66.     char temp_buf[128]={'\0'};

    67.    

    68.    

    69.     /* Set systick reload value to generate 1ms interrupt */

    70.     if (SysTick_Config(SystemCoreClock / 1000U)) {

    71.         while (1) {

    72.             

    73.         }

    74.     }

    75.         /* Board pin init */

    76.     CLOCK_EnableClock(kCLOCK_Gpio3);

    77.     CLOCK_EnableClock(kCLOCK_Gpio0);

    78.    

    79.     // 配置端口

    80.     BOARD_InitPins();

    81.    

    82.     lpadc_config_t mLpadcConfigStruct;

    83.     lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;

    84.     lpadc_conv_command_config_t mLpadcCommandConfigStruct_x;

    85.     lpadc_conv_command_config_t mLpadcCommandConfigStruct_y;



    86.     /* attach FRO 12M to FLEXCOMM4 (debug console) */

    87.     CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);

    88.     CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);



    89.     /* attach FRO HF to ADC0 */

    90.     CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1u);

    91.     CLOCK_AttachClk(kFRO_HF_to_ADC0);



    92.     /* enable VREF */

    93.     SPC0->ACTIVE_CFG1 |= 0x1;   

    94.    



    95.     BOARD_PowerMode_OD();

    96.     BOARD_InitBootClocks();

    97.     BOARD_InitDebugConsole();



    98.     // 初始化接口,代码不可省略

    99.     LED_RED_INIT(LOGIC_LED_OFF);

    100.     LED_BLUE_INIT(LOGIC_LED_OFF);

    101.     LED_GREEN_INIT(LOGIC_LED_OFF);



    102.     Lcd_Init();

    103.     QDTFT_Test_Demo();

    104.    

    105.     Lcd_Clear(BLACK);

    106.    

    107.     sprintf(temp_buf, "ADC Range: %d\r\n", g_LpadcFullRange);

    108.     Gui_DrawFont_GBK16(0, 0, WHITE, BLACK, (uint8_t *)temp_buf);

    109.    

    110.     SysTick_DelayTicks(5000U);

    111.    

    112.     while (1) {

    113.         //SysTick_DelayTicks(500U);



    114.         exec_adc_y();

    115.         exec_adc_x();

    116.     }

    117. }



    118. uint32_t exec_adc_y(void) {

    119.     uint32_t adcValue=0;

    120.     char temp_buf[128]={'\0'};



    121.     lpadc_config_t mLpadcConfigStruct;

    122.     lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;

    123.     lpadc_conv_command_config_t mLpadcCommandConfigStruct_y;

    124.    

    125.     LPADC_GetDefaultConfig(&mLpadcConfigStruct);

    126.     mLpadcConfigStruct.enableAnalogPreliminary = true;

    127.     mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE;

    128.     mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage128;

    129.     LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct);

    130.    



    131.     /* Request offset calibration. */

    132.     LPADC_DoOffsetCalibration(DEMO_LPADC_BASE);



    133.        /* Request gain calibration. */

    134.     LPADC_DoAutoCalibration(DEMO_LPADC_BASE);





    135.     /* Set conversion CMD configuration. */

    136.     LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct_y);

    137.     mLpadcCommandConfigStruct_y.channelNumber = DEMO_LPADC_USER_CHANNEL_Y;

    138.     LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID, &mLpadcCommandConfigStruct_y);

    139.    

    140.     /* Set trigger configuration. */

    141.     LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);

    142.     mLpadcTriggerConfigStruct.targetCommandId       = DEMO_LPADC_USER_CMDID;

    143.     mLpadcTriggerConfigStruct.enableHardwareTrigger = false;

    144.     LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */

    145.    

    146.     // 触发转换

    147.     LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. A通道 */

    148.     // 等待转换完成

    149.     while (!LPADC_GetConvResult(DEMO_LPADC_BASE, &mLpadcResultConfigStruct, 0U));

    150.     adcValue = ((mLpadcResultConfigStruct.convValue) >> g_LpadcResultShift);

    151.     PRINTF("Y value: %d\r\n", adcValue);

    152.     sprintf(temp_buf, "Y=%u       ", adcValue);

    153.     Gui_DrawFont_GBK16(0,16, WHITE, BLACK, (uint8_t *)temp_buf);



    154.     return adcValue;



    155. }



    156. uint32_t exec_adc_x(void) {

    157.     uint32_t adcValue=0;

    158.     char temp_buf[128]={'\0'};



    159.     lpadc_config_t mLpadcConfigStruct;

    160.     lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;

    161.     lpadc_conv_command_config_t mLpadcCommandConfigStruct_x;

    162.    

    163.     LPADC_GetDefaultConfig(&mLpadcConfigStruct);

    164.     mLpadcConfigStruct.enableAnalogPreliminary = true;

    165.     mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE;

    166.     mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage128;

    167.     LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct);

    168.    



    169.     /* Request offset calibration. */

    170.     LPADC_DoOffsetCalibration(DEMO_LPADC_BASE);



    171.        /* Request gain calibration. */

    172.     LPADC_DoAutoCalibration(DEMO_LPADC_BASE);





    173.     /* Set conversion CMD configuration. */

    174.     LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct_x);

    175.     mLpadcCommandConfigStruct_x.channelNumber = DEMO_LPADC_USER_CHANNEL_X;

    176.     LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID, &mLpadcCommandConfigStruct_x);

    177.    

    178.     /* Set trigger configuration. */

    179.     LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);

    180.     mLpadcTriggerConfigStruct.targetCommandId       = DEMO_LPADC_USER_CMDID;

    181.     mLpadcTriggerConfigStruct.enableHardwareTrigger = false;

    182.     LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */

    183.    

    184.     // 触发转换

    185.     LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U); /* 1U is trigger0 mask. A通道 */

    186.     // 等待转换完成

    187.     while (!LPADC_GetConvResult(DEMO_LPADC_BASE, &mLpadcResultConfigStruct, 0U));

    188.     adcValue = ((mLpadcResultConfigStruct.convValue) >> g_LpadcResultShift);

    189.     PRINTF("X value: %d\r\n", adcValue);

    190.     sprintf(temp_buf, "X=%u       ", adcValue);

    191.     Gui_DrawFont_GBK16(0,32, WHITE, BLACK, (uint8_t *)temp_buf);

    192.    

    193.     return adcValue;



    194. }
    复制代码


    测试效果图:
    微信图片_20240330141618.jpg
    无标题.png
    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2025-2-21 12:40
  • 签到天数: 16 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    11

    主题

    1632

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    3642
    最后登录
    2025-7-26
    发表于 2024-3-31 22:11:20 | 显示全部楼层
    前段时间刚玩了一个有意思的电路,把摇杆的两个脚的电压值信号转换成一个脚的pwm信号,PWM的占空比表示X轴位置,基础频率表示Y轴位置,挺有意思的
    ~~~~~~~~~~~~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:34
  • 签到天数: 1100 天

    连续签到: 18 天

    [LV.10]以坛为家III

    28

    主题

    4267

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5778
    最后登录
    2025-7-26
     楼主| 发表于 2024-4-1 13:03:38 | 显示全部楼层
    oxlm 发表于 2024-3-31 22:11
    前段时间刚玩了一个有意思的电路,把摇杆的两个脚的电压值信号转换成一个脚的pwm信号,PWM的占空比表示X轴 ...

    大老厉害!这个想法不错,哈哈哈。
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-27 12:24 , Processed in 0.089530 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表