AD2S1210 解调电路及模拟SPI数据读写

AD2S1210 解调电路及模拟SPI数据读写

一 硬件设计

需要用到的硬件有:

  1. STM32F103C8T6:直接淘宝买,很便宜几块钱一个,江科大版本的就行;
  2. AD2S1210解调板:淘宝只有一家,我们前期调试验证买了现成的,后续是自己设计了;
  3. 功率放大器:用的是信号发生器配套的功率放大器
  4. UAF42滤波模块:负责将正余弦信号放大,移相,使其符合AD2S1210输入要求;
  5. 调试需要的工具:面包板两块,ST-Link下载器,示波器,逻辑分析仪,杜邦线若干。

1.1 STM32F103

image-20240703145533319

首先通过CubeMX将需要使用到的引脚、时钟以及串口配置好,根据自己的需要进行修改就行了,时钟使用的是72MHz。

image-20240703151314632 image-20240703151343886 image-20240703151505446
PA3A0
PA4A1
PA5SCLK
PA6SDO
PA7SDI
PB3SAMPLE
PB4RESET
PB5NWR
PA9TX
PA10RX

1.2 AD2S1210解调

image-20240703150231390 8f687f2751bfda75635cda6a3f65b00 a903364c8477d946f5c28a82f8cb3de_副本

1.3 硬件连接

需要注意的是软件部分全部是在配置模式下进行的,所以需要把A0,A1直接拉高,或者在写寄存器之前,将A0,A1的GPIO软件拉高

20bbf7a7d722778c8d6dfa900e6cece_副本

二 软件代码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 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 <stdio.h>
#include "usart.h"
#include "gpio.h"
#include <string.h> // 包含字符串处理函数的头文件
#include "stm32f1xx_hal_conf.h"
//定义delay函数中的数据类型
#define vu32 volatile unsigned  int
	
//====A0====A1====结果
//====0 ====0 ====位置输出
//====0 ====1 ====速度输出
//====1 ====0 ====保留
//====1 ====1 ====配置模式
#define A0_H     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3, GPIO_PIN_SET)
#define A0_L     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3, GPIO_PIN_RESET)
#define A1_H     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4, GPIO_PIN_SET)
#define A1_L     HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4, GPIO_PIN_RESET)
//SPI 接口
#define SCLK_H   HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5, GPIO_PIN_SET)
#define SCLK_L   HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5, GPIO_PIN_RESET)
#define SDO      HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)
#define SDI_H    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7, GPIO_PIN_SET)
#define SDI_L    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7, GPIO_PIN_RESET)
// SAMPLE RST NWR
#define SMAPLE_H HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, GPIO_PIN_SET)
#define SMAPLE_L HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, GPIO_PIN_RESET)
#define RESET_H  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4, GPIO_PIN_SET)
#define RESET_L  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4, GPIO_PIN_RESET)
#define NCS_H    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_SET)
#define NCS_L    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_RESET)

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Delay(vu32 nCount);
void AD2S1210_WRITE(uint8_t addr,uint8_t data);
uint8_t AD2S1210_READ(uint8_t addr);
void AD2S1210_RESET(void);
uint16_t READ_Position(void);//读取位置
int16_t READ_Velocity(void);//读取速度
void sendDataToPC(uint16_t Position, int16_t Velocitys, uint8_t reg[10]);

uint16_t Position;
int16_t Velocitys;
uint8_t reg[10];
uint8_t data[14]; //发送至上位机的数据 为 Position+Velocity+ reg[10]
uint8_t buffer[15];
uint8_t Fault;
uint8_t test;
uint16_t Dos_temp;
int main(void)
{
	HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
	
	
  SCLK_H;
  SMAPLE_L;
	AD2S1210_RESET();

	AD2S1210_WRITE(0x92,0x7f);//Set 16Bit 0x7e->12Bit
  AD2S1210_WRITE(0x91,0x20);//Set Driver freq,参照datasheet Page22章节 0X20==9.8K 0x21==10.1k 0x32==15.3K
	AD2S1210_WRITE(0x8b,0x7f);//DOS复位最大阀值
  AD2S1210_WRITE(0x8c,0x01);//DOS复位最小阀值
  AD2S1210_WRITE(0x88,0x01);//LOS阀值
  AD2S1210_WRITE(0x89,0x7f);//DOS超量程阀值
  AD2S1210_WRITE(0x8a,0x7f);//DOS失配阀值
	//AD2S1210_WRITE(0x91,0x16);//写入10KHZ激励评率  (10KHz*2^15)/(10.24MHz)= 0x20(HEX表示)
	//AD2S1210_WRITE(0x91,0x20);//写入10KHZ激励评率  (10KHz*2^15)/(10.24MHz)= 0x20(HEX表示) 

	
  reg[0]=AD2S1210_READ(0x88);//LOS阀值
  reg[1]=AD2S1210_READ(0x89);//DOS超量程阀值
  reg[2]=AD2S1210_READ(0x8a);//DOS失配阀值
  reg[3]=AD2S1210_READ(0x8b);//DOS复位最大阀值
  reg[4]=AD2S1210_READ(0x8c);//DOS复位最小阀值
  reg[5]=AD2S1210_READ(0x8d);//LOT上限
  reg[6]=AD2S1210_READ(0x8e);//LOT下限
  reg[7]=AD2S1210_READ(0x91);//激励频率
  reg[8]=AD2S1210_READ(0x92);//控制寄存器
  reg[9]=AD2S1210_READ(0xff);//Fault 故障
  Delay(0xfff);
  SMAPLE_H;
  SMAPLE_L;
  Fault=AD2S1210_READ(0xff);//Fault
	//sendDataToPC(Position, Velocitys,reg);
  while (1)
  {
		Dos_temp++;
    if(Dos_temp>20000)
    {
      Dos_temp=0;
      if(Fault&0x10){AD2S1210_WRITE(0x8a,0x7f);}
    }
		//更新数据
    SMAPLE_H;
    SMAPLE_L;
    Fault     = AD2S1210_READ(0xff);//Fault
    Velocitys = READ_Velocity();
    Position  = READ_Position();
    sendDataToPC(Position, Velocitys,reg);		
		Delay(0xfff);
		//串口数据发送至上位机需要再delay之后,
		//否则发送至上位机的数据会被速度位置寄存器覆盖,导致数据写入不成功且数据为0
  }

}

void sendDataToPC(uint16_t Position, int16_t Velocitys, uint8_t reg[10]) {
    char buffer[100];
    int length;

    // 将数据整合到一个字符串中
    length = snprintf(buffer, sizeof(buffer), "Position:%u Velocity:%d Reg:%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", 
                      Position, Velocitys, 
                      reg[0], reg[1], reg[2], reg[3], reg[4], 
                      reg[5], reg[6], reg[7], reg[8], reg[9]);
    // 通过串口发送数据
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, length, HAL_MAX_DELAY);
}



uint16_t READ_Position(void)//读取位置
{
  uint16_t position;
  //SMAPLE_H;
  //SMAPLE_L;
  position=AD2S1210_READ(0x80);
  position<<=8;
  position|=AD2S1210_READ(0x81);
  return position;
}


int16_t READ_Velocity(void)//读取速度
{
  int16_t velocity;
  //SMAPLE_H;
  //SMAPLE_L;
  velocity=AD2S1210_READ(0x82);
  velocity<<=8;
  velocity|=AD2S1210_READ(0x83);
  return velocity;
}


void AD2S1210_WRITE(uint8_t addr,uint8_t data)
{
  uint8_t temp;
  SCLK_L;
  NCS_L;
  temp=addr;
  for(uint8_t s=0;s<8;s++)
  {
    SCLK_H;
    if(temp&0x80){SDI_H;}
    else{SDI_L;}
    SCLK_L;
    temp<<=1;
  }
  NCS_H;
  SCLK_H;
  Delay(0x0f);
  SCLK_L;
  NCS_L;
  temp=data;
  for(uint8_t s=0;s<8;s++)
  {
    SCLK_H;
    if(temp&0x80){SDI_H;}
    else{SDI_L;}
    SCLK_L;
    temp<<=1;
  }
  NCS_H;
  SCLK_H;
}


uint8_t AD2S1210_READ(uint8_t addr)
{
  uint8_t temp;
  SCLK_L;
  NCS_L;
  temp=addr;
  for(uint8_t s=0;s<8;s++)
  {
    SCLK_H;
    if(temp&0x80){SDI_H;}
    else{SDI_L;}
    SCLK_L;
    temp<<=1;
  }
  NCS_H;
  SCLK_H;
  Delay(0x0f);
  SCLK_L;
  NCS_L;
  temp=0;
  for(uint8_t s=0;s<8;s++)
  { 
    SCLK_H;
    SCLK_L;
    temp<<=1;
    if(SDO){temp++;}
  }
  NCS_H;
  SCLK_H;
  return temp;
}


void AD2S1210_RESET(void)
{
  SMAPLE_H;
  SMAPLE_L;
  RESET_L;
  Delay(0x5ff);
  RESET_H;
  Delay(0xff);
}

void Delay(vu32 nCount) 
{ 
  for(; nCount != 0; nCount--); 
} 

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = 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 */

三 实验效果

通过修改0x91寄存器,改变激励频率,10KHz的晶振默认输出12.2KHz左右,可以看到图片的左下角频率的改变。

5cda86df00d0d3d437954a2018c35f8

串口实验:

a48677cf8f4c4122224813407b7f7a6
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值