Post Go back to editing

使用stm32单片机普通I/O口模拟spi通讯,ad7616使用串行突发序列器,请问怎么回读结果

Category: Software
Product Number: AD7616
Software Version: 使用stm32单片机普通I/O口模拟spi通讯,ad7616使用串行突发序列器,请问怎么回读结果

#include "ad7616.h"
#include "delay.h"
#include "sdram.h"
#include "string.h"

u8 ad7616_range;

const u8 CH_DATA[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};

/* Dx引脚端口 */
const GPIO_TypeDef *PORT_LIST[18] =
{
AD7616_CONV_GPIO_Port0, AD7616_RST_GPIO_Port0, AD7616_RD_GPIO_Port0, AD7616_CS_GPIO_Port0,
AD7616_BUSY_GPIO_Port0, AD7616_D4_GPIO_Port0, AD7616_D11_GPIO_Port0, AD7616_D12_GPIO_Port0,
AD7616_D10_GPIO_Port0,

// AD7616_CONV_GPIO_Port1, AD7616_RST_GPIO_Port1, AD7616_RD_GPIO_Port1, AD7616_CS_GPIO_Port1,
// AD7616_BUSY_GPIO_Port1, AD7616_D4_GPIO_Port1, AD7616_D11_GPIO_Port1, AD7616_D12_GPIO_Port1,
// AD7616_D10_GPIO_Port1,
};

/* Dx引脚 */
const u16 PIN_LIST[18] =
{
AD7616_CONV_Pin0, AD7616_RST_Pin0, AD7616_RD_Pin0, AD7616_CS_Pin0,
AD7616_BUSY_Pin0, AD7616_D4_Pin0, AD7616_D11_Pin0, AD7616_D12_Pin0,
AD7616_D10_Pin0,

// AD7616_CONV_Pin1, AD7616_RST_Pin1, AD7616_RD_Pin1, AD7616_CS_Pin1,
// AD7616_BUSY_Pin1, AD7616_D4_Pin1, AD7616_D11_Pin1, AD7616_D12_Pin1,
// AD7616_D10_Pin1,
};

/**
* @brief AD7616端口初始化
* @param mode uint8_t 模式选择
*/
void AD7616_GPIO_Init(void)
{
u8 i;
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* 端口时钟使能 */
RCC->AHB4ENR |= RCC_GPIO_Port;

for(i = 0; i < sizeof(PIN_LIST) / sizeof(u16); i++)
{
GPIO_InitStruct.Pin = PIN_LIST[i];
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;

if(((PIN_LIST[i]==AD7616_D11_Pin0)&(PORT_LIST[i]==AD7616_D11_GPIO_Port0))||\
((PIN_LIST[i]==AD7616_D12_Pin0)&(PORT_LIST[i]==AD7616_D12_GPIO_Port0))||\
((PIN_LIST[i]==AD7616_BUSY_Pin0)&(PORT_LIST[i]==AD7616_BUSY_GPIO_Port0))||\
((PIN_LIST[i]==AD7616_D11_Pin1)&(PORT_LIST[i]==AD7616_D11_GPIO_Port1))||\
((PIN_LIST[i]==AD7616_D12_Pin1)&(PORT_LIST[i]==AD7616_D12_GPIO_Port1))||\
((PIN_LIST[i]==AD7616_BUSY_Pin1)&(PORT_LIST[i]==AD7616_BUSY_GPIO_Port1)))
{
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; //浮空输入模式
}
else
{
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
}

HAL_GPIO_Init((GPIO_TypeDef*)PORT_LIST[i], &GPIO_InitStruct); //初始化GPIO

HAL_GPIO_WritePin((GPIO_TypeDef*)PORT_LIST[i], PIN_LIST[i], GPIO_PIN_RESET);
}

HAL_GPIO_WritePin(AD7616_CS_GPIO_Port0, AD7616_CS_Pin0, GPIO_PIN_SET);
// HAL_GPIO_WritePin(AD7616_CS_GPIO_Port1, AD7616_CS_Pin1, GPIO_PIN_SET);

HAL_GPIO_WritePin(AD7616_RD_GPIO_Port0, AD7616_RD_Pin0, GPIO_PIN_SET);
// HAL_GPIO_WritePin(AD7616_RD_GPIO_Port1, AD7616_RD_Pin1, GPIO_PIN_SET);
}

/**
* @brief 向AD7616写入16位数据 串行软件模式下有效
* @param data uint16_t 数据
*/
static void AD7616_Write_Serial_Word(uint16_t data)
{
u16 i;
u16 shift = 0x8000;

for(i = 0; i < 16; i++)
{
bool level = shift & data;

if(level)
{
AD7616_D10_GPIO_Port0->BSRRL = AD7616_D10_Pin0;
}
else
{
AD7616_D10_GPIO_Port0->BSRRH = AD7616_D10_Pin0;
}
shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;
AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}
}

/**
* @brief 写寄存器
* @param address uint8_t 寄存器地址
* @param data uint8_t 数据
*/
static void AD7616_Write_Register(uint8_t address, uint8_t data)
{
u16 wrtie_data = 0;
u16 shift = 0x8000;
u16 i;

/* 选择写命令,必须将位D15设为1 */
wrtie_data = (((uint16_t)address << 9) | 0x8000) | (u16)data;

AD7616_CS_GPIO_Port0->BSRRH = AD7616_CS_Pin0 ;

for(i = 0; i < 16; i++)
{
bool level = shift & wrtie_data;

if(level)
{
AD7616_D10_GPIO_Port0->BSRRL = AD7616_D10_Pin0;
}
else
{
AD7616_D10_GPIO_Port0->BSRRH = AD7616_D10_Pin0;
}
shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;
AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}

AD7616_CS_GPIO_Port0->BSRRL = AD7616_CS_Pin0 ;
}

/**
* @brief 配置AD7616量程
* @param range uint8_t 量程
*/
static void AD7616_Set_Range(uint8_t range)
{
u8 range_data = 0;
ad7616_range = range;
range_data = (range << 6) | (range << 4) | (range << 2) | range;

AD7616_Write_Register(Input_Range_Register_A1, range_data);
AD7616_Write_Register(Input_Range_Register_A2, range_data);
AD7616_Write_Register(Input_Range_Register_B1, range_data);
AD7616_Write_Register(Input_Range_Register_B2, range_data);
}

static void AD7616_Write(u16 u16data)
{
u8 i;
u16 shift = 0x8000;

AD7616_CS_GPIO_Port0->BSRRH = AD7616_CS_Pin0 ;

for(i = 0; i < 16; i++)
{
bool level = shift & u16data;

if(level)
{
AD7616_D10_GPIO_Port0->BSRRL = AD7616_D10_Pin0;
}
else
{
AD7616_D10_GPIO_Port0->BSRRH = AD7616_D10_Pin0;
}
shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;
AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}

AD7616_CS_GPIO_Port0->BSRRL = AD7616_CS_Pin0 ;
}


//序列器
static void AD7616_Sequencer(void)
{
// AD7616_Write(0xC000);
// AD7616_Write(0xC211);
// AD7616_Write(0xC522);
// AD7616_Write(0x0000);
u8 i;
u16 wrtie_data;
u16 shift = 0x8000;

for(i = 0; i < 32; i++)
{
AD7616_Write_Register(0x20+i,CH_DATA[i%8]);
}

/* 选择写命令,必须将位D15设为1 */
wrtie_data = (((uint16_t)0x20 << 9) | 0x8000) | (u16)0x00 | 0x100;

AD7616_CS_GPIO_Port0->BSRRH = AD7616_CS_Pin0 ;

for(i = 0; i < 16; i++)
{
bool level = shift & wrtie_data;
if(level)
{
AD7616_D10_GPIO_Port0->BSRRL = AD7616_D10_Pin0;
}
else
{
AD7616_D10_GPIO_Port0->BSRRH = AD7616_D10_Pin0;
}
shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;
AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}

AD7616_CS_GPIO_Port0->BSRRL = AD7616_CS_Pin0 ;
}

/**
* @brief 设置AD7616串行输出模式
* @param format uint8_t 格式
*/
void AD7616_Set_Serial_Output_Format(uint8_t format)
{
if(format == Line_1_Output)
{
HAL_GPIO_WritePin(AD7616_D4_GPIO_Port0, AD7616_D4_Pin0, GPIO_PIN_RESET);
}
else if(format == Line_2_Output)
{
HAL_GPIO_WritePin(AD7616_D4_GPIO_Port0, AD7616_D4_Pin0, GPIO_PIN_SET);
}
}

/**
* @brief AD7616复位
*/
void AD7616_Reset(void)
{
AD7616_RST_GPIO_Port0->BSRRH = AD7616_RST_Pin0 ;
AD7616_RST_GPIO_Port1->BSRRH = AD7616_RST_Pin1 ;
delay_ms(1);
AD7616_RST_GPIO_Port0->BSRRL = AD7616_RST_Pin0 ;
AD7616_RST_GPIO_Port1->BSRRL = AD7616_RST_Pin1 ;
delay_ms(10);
}

/**
* @brief 启动AD7616转换
*/
void AD7616_Conversion(void)
{
u8 i = 0;

AD7616_CONV_GPIO_Port0->BSRRH = AD7616_CONV_Pin0;
// delay_us(1);
AD7616_CONV_GPIO_Port0->BSRRL = AD7616_CONV_Pin0;
}

/**
* @brief 获取AD7616串行通道数据
* @return uint16_t 通道数据
*/
static void AD7616_Get_Serial_Data(uint16_t *data)
{
u8 i,j;
u16 shift = 0x8000;
GPIO_PinState state = GPIO_PIN_RESET;

for(i = 0; i < 32*2; i += 2)
{
shift = 0x8000;
for(j = 0; j< 16; j++)
{
AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;

state = HAL_GPIO_ReadPin(AD7616_D12_GPIO_Port0, AD7616_D12_Pin0); //读取DB12引脚
if(state == GPIO_PIN_SET)
{
data[i] |= shift;
}
else if(state == GPIO_PIN_RESET)
{
data[i] &= (~shift);
}

state = HAL_GPIO_ReadPin(AD7616_D11_GPIO_Port0, AD7616_D11_Pin0); //读取DB11引脚
if(state == GPIO_PIN_SET)
{
data[i+1] |= shift;
}
else if(state == GPIO_PIN_RESET)
{
data[i+1] &= (~shift);
}

shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}

delay_us(1);
}

}

/**
* @brief 获取AD7616单次采集数据
* @param data uint16_t 数组指针
*/
void AD7616_Read_Data(u16 *u16data)
{
u16 i = 0, j = 0;
u16 shift = 0x8000;
GPIO_PinState busy = GPIO_PIN_SET;
GPIO_PinState state[2] = {GPIO_PIN_RESET};

do
{
busy = AD7616_BUSY_GPIO_Port0->IDR & AD7616_BUSY_Pin0;
}
while(busy);

AD7616_Write(0x0000);

AD7616_CS_GPIO_Port0->BSRRH = AD7616_CS_Pin0;
delay_us(1);

for(i = 0; i < 32*2; i+=2)
{
shift = 0x8000;
for(j = 0; j < 16; j++)
{
AD7616_RD_GPIO_Port0->BSRRH = AD7616_RD_Pin0;

state[0] = HAL_GPIO_ReadPin(AD7616_D12_GPIO_Port0, AD7616_D12_Pin0); //读取DB12引脚
state[1] = HAL_GPIO_ReadPin(AD7616_D11_GPIO_Port0, AD7616_D11_Pin0); //读取DB11引脚

if(state[0] == GPIO_PIN_SET)
{
u16data[i] |= shift;
}
else
{
u16data[i] &= (~shift);
}

if(state[1] == GPIO_PIN_SET)
{
u16data[i+1] |= shift;
}
else
{
u16data[i+1] &= (~shift);
}

shift >>= 1;

AD7616_RD_GPIO_Port0->BSRRL = AD7616_RD_Pin0;
}

delay_us(1);
}

AD7616_CS_GPIO_Port0->BSRRL = AD7616_CS_Pin0;
}


void AD7616_Init(uint8_t format, uint8_t range)
{
AD7616_GPIO_Init();
AD7616_Set_Range(range); //量程
AD7616_Sequencer(); //序列器
AD7616_Write_Register(Config_Register, 0x64); //配置寄存器
// AD7616_Write(0x8464);
AD7616_Reset(); //复位
AD7616_Set_Serial_Output_Format(format); //2个串口

AD7616_Conversion();
}


/**
* @brief 将数字量转换为电压量
* @param data uint16_t 数字量
* @return double 电压量 单位毫伏(mv)
*/
double AD7616_Digital2Voltage(uint16_t data)
{
int16_t signed_data = data;

switch (ad7616_range)
{
case Range_2_5_V:
return signed_data * 5.0 / 65536.0 * 1000.0;

case Range_5_V:
return signed_data * 10.0 / 65536.0 * 1000.0;

case Range_10_V:
return signed_data * 20.0 / 65536.0 * 1000.0;
}
return 0;
}

Parents
  • 这取决于您设置的转换order, sequences,和通信模式,是serial 1-wire, serial 2-wire, or parallel mode。

  • 不好意思打扰您,我有个问题想请教您

    就是我用的是AD7616,模式是软件串行模式,输入范围16个通道都是±5,采用序列器的突发模式,用SPI和STM32通信。


    使用时,将VxGND全部悬空,每一路单独使用时(Vx接正电压,VxGND接地),仅有V5B和V6B有异常,其他十四个通道都数值正常。


    将所有通道的VxGND接地时,逻辑分析仪抓到的值不正常,如图所示。有8个通道会一直抓不到数据,而且只能读到V0A、V0B、V1B、V2B、V3B、V4B、V5B、V6B的值(按顺序依次出现)

    您知道是什么问题吗,寄存器也成功写入了,时序我抓了也是对的

  • 逻辑分析仪上这些波形每个颜色的都代表什么信号呢?麻烦标清楚。您之前说2个通道异常,14个通道正常。之后又说8个通道抓不到数值。而且逻辑分析仪抓到的数值不对?我不太明白,现在你遇到的问题具体是什么个现象。

Reply Children
No Data