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

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



PA3 | A0 |
---|---|
PA4 | A1 |
PA5 | SCLK |
PA6 | SDO |
PA7 | SDI |
PB3 | SAMPLE |
PB4 | RESET |
PB5 | NWR |
PA9 | TX |
PA10 | RX |
1.2 AD2S1210解调



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

二 软件代码
/* 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左右,可以看到图片的左下角频率的改变。

串口实验:
