|
|
初学者,用STM32H7+AD7606B采集1HZ正弦波,没有用定时器和中断,单纯GPIO口控制引脚,为什么会出现图中状况,麻烦各位大佬看一下是什么原因,谢谢!

/* 系统时钟频率 */
#define SYS_FREQ 480000000UL
#define CYCLES_PER_US (SYS_FREQ / 1000000UL) // 480
/* 确保DWT已启用 */
static inline void DWT_Init(void)
{
if (!(DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk)) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
}
/* 基于DWT的精确延时(纳秒级)*/
static inline void AD7606B_Delay_ns(uint32_t ns)
{
if (ns < 10) return; // 小于10ns不延时
uint32_t cycles = (ns * CYCLES_PER_US + 999) / 1000;
uint32_t start = DWT->CYCCNT;
while ((DWT->CYCCNT - start) < cycles);
}
/* 基于DWT的微秒延时 */
static inline void AD7606B_Delay_us(uint32_t us)
{
uint32_t cycles = us * CYCLES_PER_US;
uint32_t start = DWT->CYCCNT;
while ((DWT->CYCCNT - start) < cycles);
}
void AD7606B_Init(void)
{
/* 初始化DWT(如果尚未初始化) */
DWT_Init();
/* 模式配置 */
AD7606B_SER_L; // 并行模式
AD7606B_STBY_H; // 退出待机模式,进入工作模式
/* 控制引脚初始状态 */
AD7606B_RD_H; // RD初始高电平
AD7606B_CS_H; // CS初始高电平(禁用芯片)
/* 过采样设置 - 无过采样(最高速率) */
AD7606B_OS0_L; // OS[2:0] = 000
AD7606B_OS1_L; // 无过采样,200kSPS每通道
AD7606B_OS2_L; // 或800kSPS总吞吐量
// /* 硬件稳定时间 */
// HAL_Delay(1); // 使用HAL延时更可靠
/* 硬件稳定时间 */
AD7606B_Delay_us(1000); // 1ms延时,使用DWT
}
void AD7606B_Reset(void)
{
/* 根据数据手册:完全复位需要3μs高电平脉冲 */
AD7606B_RESET_L;
AD7606B_Delay_ns(100); // 100ns低电平
AD7606B_RESET_H;
// AD7606B_Delay_ns(3000);
AD7606B_Delay_us(3); // 3μs高电平脉冲 //
AD7606B_RESET_L;
// /* 复位后设备建立时间(50ns) */
// HAL_Delay(1); // 1ms,远大于253μs,确保稳定
/* 复位后设备建立时间(根据数据手册至少253μs) */
AD7606B_Delay_us(254); // 稍微大于最小值确保稳定
}
void AD7606B_Start(void)
{
/* CONVST脉冲:低电平至少10ns,高电平至少10ns */
AD7606B_CONVST_L;
AD7606B_Delay_ns(20); // 20ns低电平(大于最小值10ns)
AD7606B_CONVST_H;
AD7606B_Delay_ns(20); // 20ns高电平
// 注意:连续CONVST上升沿之间至少1.25μs
}
/* 获取单通道16位数据 */
static uint16_t AD7606B_Get_PinData(void)
{
uint16_t result = 0;
/* 读取16个数据引脚 */
for (uint8_t i = 0; i < 16; i++)
{
if (HAL_GPIO_ReadPin(data_pins.port, data_pins.pin) == GPIO_PIN_SET)
{
result |= (1 << i);
}
}
return result;
}
void AD7606B_Get_Data(uint16_t *data)
{
uint32_t timeout = 1000000; // 超时计数器
/* 等待BUSY变低(转换完成) */
while (AD7606B_BUSY == GPIO_PIN_SET)
{
if (--timeout == 0) {
/* 超时处理 */
return;
}
}
/* 使能芯片 */
AD7606B_CS_L;
AD7606B_Delay_ns(5); // CS下降沿到RD下降沿建立时间
for (uint8_t i = 0; i < AD7606B_CHANNEL_MAX; i++)
{
/* RD脉冲:低电平至少10ns,高电平至少10ns */
AD7606B_RD_L;
AD7606B_Delay_ns(15); // 15ns低电平(大于最小值10ns)
AD7606B_RD_H;
AD7606B_Delay_ns(15); // 数据建立时间(RD上升沿后数据至少保持12ns)
/* 读取数据 - 在RD高电平期间读取 */
data = AD7606B_Get_PinData();
/* RD周期时间:至少30ns(V_DRIVE>2.7V时) */
if (i < AD7606B_CHANNEL_MAX - 1)
{
AD7606B_Delay_ns(30); // 确保RD周期时间
}
}
/* 禁用芯片 */
AD7606B_Delay_ns(5); // RD上升沿到CS上升沿保持时间(最小值0ns)
AD7606B_CS_H;
}
static double AD7606B_Range_Digital2Voltage(uint16_t data, uint8_t range)
{
int16_t signed_data = (int16_t)data;
switch (range) {
case Range_2_5_V:
return signed_data * 5.0 / 65536.0;
case Range_5_V:
return signed_data * 10.0 / 65536.0;
case Range_10_V:
return signed_data * 20.0 / 65536.0;
default:
return 0;
}
}
void AD7606B_Get_Voltage(uint16_t *data, double *voltage_data, uint8_t range)
{
for (uint8_t i = 0; i < AD7606B_CHANNEL_MAX; i++)
{
voltage_data = AD7606B_Range_Digital2Voltage(data, range);
}
}
/* 完整的单次采集流程 */
void AD7606B_Single_Acquisition(double *voltage_data, uint8_t range)
{
uint16_t raw_data[AD7606B_CHANNEL_MAX];
/* 1. 启动转换 */
AD7606B_Start();
/* 2. 等待并读取数据 */
AD7606B_Get_Data(raw_data);
/* 3. 转换为电压 */
AD7606B_Get_Voltage(raw_data, voltage_data, range);
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* 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 */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
ADSerial_Init();
AD7606B_Init();
AD7606B_Reset();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
AD7606B_Single_Acquisition(AD7606B_Voltage, Range_10_V);
printf("%.3f\r\n", AD7606B_Voltage[0]);
// HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
|
-
|