ADX112驱动从0开始(STM32)

从0开始写ADX112驱动(STM32)

步骤1:CUBE_MX先选你要的芯片 我用的G070(最便宜的那颗)

步骤2:时钟配置 你要多大时钟直接拉满

步骤3:生成工程

步骤4:打开工程点开main.c里面 hal_conf.h 的头文件

步骤5:删除SPI的注释,这里我们要啥功能就删除什么东西的注释

步骤6:新建ADX112.c/ADX112.h文件

右键添加ADX112.c到工程

整完以后可以直接用VS Code 打开Keil工程

安装这个插件

然后就这样,那样

但是他不能直接跳转到,.h 文件之类,配置起来较为麻烦,还是直接写,配合KEIL就行

配置一下引脚,右键选择跳转到定义配置为输入引脚

写ADX112驱动的壳

使用Code block 可以直接运行C 不用配置什么环境

#include <stdio.h>

#include <stdlib.h>

#define DR_8SPS         0b0000000000000000

#define DR_16SPS        0b0000000000100000

#define DR_32SPS        0b0000000001000000

#define DR_64SPS        0b0000000001100000

#define DR_128SPS       0b0000000010000000

#define DR_250SPS       0b0000000010100000

#define DR_475SPS       0b0000000011000000

#define DR_860SPS       0b0000000011100000

#define MUX_PA0_NA1         0b0000000000000000

#define MUX_PA0_NA3         0b0001000000000000

#define MUX_PA1_NA3         0b0010000000000000

#define MUX_PA2_NA3         0b0011000000000000

#define MUX_PA0_NGND        0b0100000000000000

#define MUX_PA1_NGND        0b0101000000000000

#define MUX_PA2_NGND        0b0110000000000000

#define MUX_PA3_NGND        0b0111000000000000

#define MODE_CONTIUOUS      0b0000000000000000

#define MODE_POWERDOWN      0b0000000100000000

#define Single_Conversion_DIS 0b0000000000000000

#define Single_Conversion_SSC    0b1000000000000000

#define PGA_GAIN_6_144      0b0000000000000000

#define PGA_GAIN_4_096      0b0000001000000000

#define PGA_GAIN_2_048      0b0000010000000000

#define PGA_GAIN_0_024      0b0000011000000000

#define PGA_GAIN_0_512      0b0000100000000000

#define PGA_GAIN_0_256      0b0000101000000000

#define TS_MODE_ADC         0b0000000000000000

#define TS_MODE_TS          0b0000000000010000

#define PULL_UP_DOUT_PullupDis        0b0000000000000000

#define PULL_UP_DOUT_PullupEn         0b0000000000001000

#define NOP_UPdata_NUPConfig          0b0000000000000000

#define NOP_UPdata_UPConfig           0b0000000000000010

//ADX112结构体

typedef struct

{

        int MUX;

        int PGA_GAIN;

        int DR;

        int MODE;

        int TS_MODE;

        int Single_Conversion;

        int PULL_UP_DOUT;

        int NOP;

} ADX112_InitTypeDef;

void ADX112_Get_ADValue(ADX112_InitTypeDef * Config)

{

    int data;

    data=(Config->MUX)|(Config->PGA_GAIN)|(Config->DR)|(Config->MODE)

    |(Config->TS_MODE)|(Config->Single_Conversion)|(Config->PULL_UP_DOUT)|(Config->NOP);

    printf("%d\r\n",data);

}

int main()

{

    ADX112_InitTypeDef ADX112_Init;

    ADX112_Init.MUX=MUX_PA0_NA3;

    ADX112_Init.PGA_GAIN=PGA_GAIN_6_144;

    ADX112_Init.DR= DR_16SPS;

    ADX112_Init.MODE=MODE_CONTIUOUS;

    ADX112_Init.PULL_UP_DOUT=PULL_UP_DOUT_PullupEn;

    ADX112_Init.Single_Conversion=Single_Conversion_DIS;

    ADX112_Init.TS_MODE=TS_MODE_ADC;

    while(1)

    {

        ADX112_Get_ADValue(&ADX112_Init);

    }

    return 0;

}

运行结果如下,是我们所期望的值

SPI数据发送CYCLE

咱们使用16位数据传输格式 (下图来自ADX112手册)

If CONFIG REGISTER data are not required to be read back, the ADX112 conversion data can also be clocked out in a short 16-bit data transmission cycle, as shown in Figure 23. Therefore, CS must be taken high after the 16th SCLK cycle. Taking CS high resets the SPI interface. The next time CS is taken low, data transmission starts with the currently buffered conversion result on the first SCLK rising edge. If DOUT/DRDY is low when data starts, the conversion buffer is already updated with a new result. Otherwise, if DOUT/DRDY is high, the same result from the data transmission cycle is read.

SCLK 时序图如上,下降沿传输数据

综合壳和SPI底层驱动

ADX112.C文件

#include "ADX112.h"

void ADX112_GPIO_Init(void)

{

  //初始化ADX112要用的GPIO

  static GPIO_InitTypeDef  GPIO_InitStruct = {0};

  //使能各个引脚的时钟

  CS_PORT_CLK_ENABLE;

  SCLK_PORT_CLK_ENABLE;

  MISO_PORT_CLK_ENABLE;

  MOSI_PORT_CLK_ENABLE;

  //配置各个引脚

   

  //CS 引脚

  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;

  GPIO_InitStruct.Pull  = GPIO_PULLUP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStruct.Pin = CS_PIN;

  HAL_GPIO_Init(CS_PORT, &GPIO_InitStruct);

  //MOSI 引脚

  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;

  GPIO_InitStruct.Pull  = GPIO_PULLUP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStruct.Pin = MOSI_PIN;

  HAL_GPIO_Init(MOSI_PORT, &GPIO_InitStruct);

  //SCLK 引脚

  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;

  GPIO_InitStruct.Pull  = GPIO_PULLUP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStruct.Pin = SCLK_PIN;

  HAL_GPIO_Init(SCLK_PORT, &GPIO_InitStruct);

  //MISO 引脚

  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;

  GPIO_InitStruct.Pull  = GPIO_PULLUP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStruct.Pin = MISO_PIN;

  HAL_GPIO_Init(MISO_PORT, &GPIO_InitStruct);

  CS_H;

  SCLK_H;

  MOSI_L;

}

//配置ADX112 读写

uint16_t ADX112_Get_ADValue(ADX112_InitTypeDef* Config)

{

  uint16_t data,i,wdata;

  //将结构体指针的参数赋值给wdata

  wdata=(Config->MUX)|(Config->PGA_GAIN)|(Config->DR)|(Config->MODE)

  |(Config->TS_MODE)|(Config->Single_Conversion)|(Config->PULL_UP_DOUT)|(Config->NOP);

 

  //拉低时钟开始传输数据

  CS_L;

  for (i = 0; i < 16; i++)

  {

      SCLK_H;

      data<<=1;

      //如果最高位为1则写1否则写0

      if((wdata&0X8000)==0X8000)

      {

        MOSI_H;

      }

      else

      {

        MOSI_L;

      }

      //如果MISO 是高则最低位加1

      //如果MISO 是低则不加

      data=data+MISO;

      SCLK_L;

      //每次传输完一个数据 配置左移一位

      wdata<<=1;

     

  }

  CS_H;

  return data;

}

ADX112.h文件

//定义头文件名字

#ifndef __ADX112_H

#define __ADX112_H

//用的MCU什么型号写啥 我这里用的是G0 所以拷贝这个

#include "stm32f4xx_hal.h"

//宏定义 将MOSI的PIN指定到那个PIN

#define MOSI_PIN    GPIO_PIN_3

#define MISO_PIN    GPIO_PIN_1

#define SCLK_PIN    GPIO_PIN_2

#define CS_PIN      GPIO_PIN_10

//定义SPI所使用的端口

//换MCU或者改端口时候直接改宏定义就好了

#define MOSI_PORT   GPIOA

#define MISO_PORT   GPIOA

#define SCLK_PORT   GPIOA

#define CS_PORT     GPIOA

//定义各个引脚的时钟

#define CS_PORT_CLK_ENABLE   __HAL_RCC_GPIOC_CLK_ENABLE()

#define SCLK_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE()

#define MISO_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE()

#define MOSI_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE()

//定义引脚输出输入代号 可以少打点字

#define CS_H        HAL_GPIO_WritePin(CS_PORT,CS_PIN,GPIO_PIN_SET)

#define CS_L        HAL_GPIO_WritePin(CS_PORT,CS_PIN,GPIO_PIN_RESET)

#define MOSI_H      HAL_GPIO_WritePin(MOSI_PORT,MOSI_PIN,GPIO_PIN_SET)

#define MOSI_L      HAL_GPIO_WritePin(MOSI_PORT,MOSI_PIN,GPIO_PIN_RESET)

#define SCLK_H      HAL_GPIO_WritePin(SCLK_PORT,SCLK_PIN,GPIO_PIN_SET)

#define SCLK_L      HAL_GPIO_WritePin(SCLK_PORT,SCLK_PIN,GPIO_PIN_RESET)

#define MISO        HAL_GPIO_ReadPin(MISO_PORT,MISO_PIN)

//定义ADX112的配置

#define DR_8SPS         0x0000

#define DR_16SPS        0x0020

#define DR_32SPS        0x0040

#define DR_64SPS        0x0060

#define DR_128SPS       0x0080

#define DR_250SPS       0x00a0

#define DR_475SPS       0x00c0

#define DR_860SPS       0x00e0

#define MUX_PA0_NA1         0x0000

#define MUX_PA0_NA3         0x1000

#define MUX_PA1_NA3         0x2000

#define MUX_PA2_NA3         0x3000

#define MUX_PA0_NGND    0x4000

#define MUX_PA1_NGND    0x5000

#define MUX_PA2_NGND    0x6000

#define MUX_PA3_NGND    0x7000

#define MODE_CONTIUOUS      0x0000

#define MODE_POWERDOWN    0x0100

#define Single_Conversion_DIS 0x0000

#define Single_Conversion_SSC    0x8000

#define PGA_GAIN_6_144      0x0000

#define PGA_GAIN_4_096      0x0200

#define PGA_GAIN_2_048      0x0400

#define PGA_GAIN_0_024      0x0600

#define PGA_GAIN_0_512    0x0800

#define PGA_GAIN_0_256    0x0a00

#define TS_MODE_ADC         0x0000

#define TS_MODE_TS          0x0010

#define PULL_UP_DOUT_PullupDis        0x0000

#define PULL_UP_DOUT_PullupEn         0x0008

#define NOP_Pdata_NPConfig          0x0000

#define NOP_Pdata_PConfig           0x0002

//ADX112结构体

typedef struct

{

        uint16_t MUX;

        uint16_t PGA_GAIN;

        uint16_t DR;

        uint16_t MODE;

        uint16_t TS_MODE;

        uint16_t Single_Conversion;

        uint16_t PULL_UP_DOUT;

        uint16_t NOP;

} ADX112_InitTypeDef;

//将ADX112 各个bit 信息拷贝至此

/**************************************

 *    ADX112 Register CONFIG

 **************************************

 *    Bit 15    /   Single Conversion

 *    Bit 14    /   MUX

 *    Bit 13    /   MUX

 *    Bit 12    /   MUX

 *    Bit 11    /   PGA

 *    Bit 10    /   PGA

 *    Bit 9      /   PGA

 *    Bit 8      /   MODE

 *    Bit 7      /   DR

 *    Bit6       /   DR

 *    Bit5       /   DR

 *    Bit4       /   TS_MODE

 *    Bit3       /   PULL_UP_DOUT

 *    Bit2       /   NOP

 *    Bit1       /   NOP

 *    Bit 0      /   Reserved

 * |15-12  |11-8  |7-4 |3-0|

 *    8421  8421  8421 8421

 *    0~~~  0100  1000 0010

 *                  

 *************************************/

 /************************************

    MUX=100 AINP = AIN0     0x4

    MUX=101 AINP = AIN1     0x5

    MUX=110 AINP = AIN2     0x6

    MUX=111 AINP = AIN3     0x7

    FULL SCALE RANGE =>  2.048 V

    DATE RATE        =>  860 SPS

   

 ************************************/

/* ADX112 初始化 */

void ADX112_GPIO_Init(void);

uint16_t ADX112_Get_ADValue(ADX112_InitTypeDef * Config);

#endif

后续将ADX112_Init改为ADX112_GPIO_Init 避免混淆

验证SPI

Main.c

/* USER CODE BEGIN Header */

/**

  ******************************************************************************

  * @file           : main.c

  * @brief          : Main program body

  ******************************************************************************

  * @attention

  *

  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.

  * All rights reserved.</center></h2>

  *

  * This software component is licensed by ST under BSD 3-Clause license,

  * the "License"; You may not use this file except in compliance with the

  * License. You may obtain a copy of the License at:

  *                        opensource.org/licenses/BSD-3-Clause

  *

  ******************************************************************************

  */

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "ADX112.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

/* 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 */

/* 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 */

    ADX112_InitTypeDef ADX112_Init;

    uint16_t ADC_Value;

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */

  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

   

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */

  /* USER CODE BEGIN 2 */

     ADX112_GPIO_Init();

 

  ADX112_Init.MUX=MUX_PA0_NA3;

  ADX112_Init.PGA_GAIN=PGA_GAIN_6_144;

  ADX112_Init.DR= DR_16SPS;

  ADX112_Init.MODE=MODE_CONTIUOUS;

  ADX112_Init.PULL_UP_DOUT=PULL_UP_DOUT_PullupEn;

  ADX112_Init.Single_Conversion=Single_Conversion_DIS;

  ADX112_Init.TS_MODE=TS_MODE_ADC;

  ADC_Value=ADX112_Get_ADValue(&ADX112_Init);

  /* USER CODE END 2 */

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    /* USER CODE END WHILE */

        ADC_Value=ADX112_Get_ADValue(&ADX112_Init);

        HAL_Delay(500);

    /* 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

  */

  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters

  * in the RCC_OscInitTypeDef structure.

  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

  RCC_OscInitStruct.HSIState = RCC_HSI_ON;

  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;

  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;

  RCC_OscInitStruct.PLL.PLLN = 8;

  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

  {

    Error_Handler();

  }

}

/* USER CODE BEGIN 4 */

/* 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 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

没有挂ADX112时候逻辑分析仪输出

满足我们的设定,OK 挂上芯片就刚好。

posted @ 2023-02-16 17:18  xuyuntong  阅读(319)  评论(0编辑  收藏  举报