Fix bugs in AD57X4 driver implemenation

This commit is contained in:
Jan-Henrik 2020-04-18 23:58:04 +02:00
parent 30a86fbdd9
commit 3da627830d
4 changed files with 47 additions and 22 deletions

View file

@ -1,8 +1,8 @@
#include "ad57x4.h" #include "ad57x4.h"
#include "peripherals.h" #include "peripherals.h"
#include "spi_mode.h" #include "spi_mode.h"
#include <stm32f3xx_hal.h>
#include <math.h> #include <math.h>
#include <stm32f3xx_hal.h>
static const uint32_t kPinEnable = GPIO_PIN_5; static const uint32_t kPinEnable = GPIO_PIN_5;
@ -16,26 +16,34 @@ void AD57X4::Init()
HAL_GPIO_Init(GPIOB, &init); HAL_GPIO_Init(GPIOB, &init);
HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET);
this->Write(REGISTER_CONTROL, 1, 0b100);
} }
void AD57X4::WriteVoltage(uint8_t dac, float voltage) { void AD57X4::WriteVoltage(uint8_t dac, float voltage)
{
CONSTRAIN(voltage, -10.799f, 10.799f);
VoltageRange range = VOLTAGE_RANGE_FIVE_VOLTS; VoltageRange range = VOLTAGE_RANGE_FIVE_VOLTS;
if(fabs(voltage) > 5) range = VOLTAGE_RANGE_TEN_VOLTS; if (fabs(voltage) > 5)
if(fabs(voltage) > 10) range = VOLTAGE_RANGE_TEN_EIGHT_VOLTS; range = VOLTAGE_RANGE_TEN_VOLTS;
if (fabs(voltage) > 10)
range = VOLTAGE_RANGE_TEN_EIGHT_VOLTS;
float multiplier = 2.0f; float multiplier = 2.0f;
if(range == VOLTAGE_RANGE_TEN_VOLTS) multiplier = 4.0f; if (range == VOLTAGE_RANGE_TEN_VOLTS)
if(range == VOLTAGE_RANGE_TEN_EIGHT_VOLTS) multiplier = 4.32f; multiplier = 4.0f;
if (range == VOLTAGE_RANGE_TEN_EIGHT_VOLTS)
multiplier = 4.32f;
float refin = 2.5f; float refin = 2.5f;
if (voltage < 0) { if (voltage < 0) {
// convert to signed value // convert to signed value
int16_t value = (voltage / (multiplier * refin)) * (65535.0f); int16_t value = (32768.0f * voltage) / (multiplier * refin);
this->WriteDacBipolar(dac, range, value); this->WriteDacBipolar(dac, range, value);
} else { } else {
// convert to unsigned value // convert to unsigned value
uint16_t value = (voltage / (multiplier * refin)) * (65535.0f); uint16_t value = (65536.0f * voltage) / (multiplier * refin);
this->WriteDacUnipolar(dac, range, value); this->WriteDacUnipolar(dac, range, value);
} }
@ -47,17 +55,25 @@ void AD57X4::EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar)
// power on dac // power on dac
this->dacPower |= 1 << dac; this->dacPower |= 1 << dac;
this->Write(REGISTER_POWER_CONTROL, 0, this->dacPower); this->Write(REGISTER_POWER_CONTROL, 0, this->dacPower);
for (int i = 0; i < 10000; i++)
asm("nop");
} }
if (this->dacRange[dac] != range) { if (this->dacRange[dac] != range || this->dacBipolar[dac] != bipolar) {
this->Write(REGISTER_OUTPUT_RANGE, dac, range + (bipolar ? 3 : 0)); this->Write(REGISTER_OUTPUT_RANGE, dac, range + (bipolar ? 3 : 0));
this->dacRange[dac] = range; this->dacRange[dac] = range;
this->dacBipolar[dac] = bipolar;
} }
} }
void AD57X4::WriteDac(uint8_t dac, VoltageRange range, uint16_t value, bool bipolar) {
EnableAndSetRange(dac, range, bipolar);
this->Write(REGISTER_DAC, dac, value);
this->Write(REGISTER_CONTROL, 0b101, 0); // LOAD command in Control Register
}
void AD57X4::WriteDacUnipolar(uint8_t dac, VoltageRange range, uint16_t value) void AD57X4::WriteDacUnipolar(uint8_t dac, VoltageRange range, uint16_t value)
{ {
EnableAndSetRange(dac, range, false); WriteDac(dac, range, value, false);
this->Write(REGISTER_DAC, dac, value);
} }
void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value) void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value)
@ -66,9 +82,7 @@ void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value)
if (value < 0) { if (value < 0) {
twosComplement = ~(-value) + 1; twosComplement = ~(-value) + 1;
} }
WriteDac(dac, range, twosComplement, true);
EnableAndSetRange(dac, range, true);
this->Write(REGISTER_DAC, dac, twosComplement);
} }
void AD57X4::Write(Register reg, uint8_t address, uint16_t data) void AD57X4::Write(Register reg, uint8_t address, uint16_t data)
@ -82,6 +96,7 @@ void AD57X4::Write(Register reg, uint8_t address, uint16_t data)
HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi2, &first, 1, HAL_MAX_DELAY); // write data HAL_SPI_Transmit(&hspi2, &first, 1, HAL_MAX_DELAY); // write data
HAL_SPI_Transmit(&hspi2, reinterpret_cast<uint8_t*>(&data), 2, HAL_MAX_DELAY); HAL_SPI_Transmit(&hspi2, reinterpret_cast<uint8_t*>(&data) + 1, 1, HAL_MAX_DELAY);
HAL_SPI_Transmit(&hspi2, reinterpret_cast<uint8_t*>(&data), 1, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET);
} }

View file

@ -12,8 +12,8 @@ enum VoltageRange {
enum Register { enum Register {
REGISTER_DAC = 0, REGISTER_DAC = 0,
REGISTER_OUTPUT_RANGE = 1, REGISTER_OUTPUT_RANGE = 1,
REGISTER_CONTROL = 2, REGISTER_CONTROL = 3,
REGISTER_POWER_CONTROL = 3 REGISTER_POWER_CONTROL = 2
}; };
class AD57X4 { class AD57X4 {
@ -34,6 +34,8 @@ class AD57X4 {
private: private:
uint8_t dacPower = 0; uint8_t dacPower = 0;
VoltageRange dacRange[4]; VoltageRange dacRange[4];
bool dacBipolar[4];
void WriteDac(uint8_t dac, VoltageRange range, uint16_t value, bool bipolar);
void EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar); void EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar);
void Write(Register reg, uint8_t address, uint16_t data); void Write(Register reg, uint8_t address, uint16_t data);
DISALLOW_COPY_AND_ASSIGN(AD57X4); DISALLOW_COPY_AND_ASSIGN(AD57X4);

View file

@ -45,7 +45,7 @@ void InitSPIAD5754(void)
hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

View file

@ -112,7 +112,7 @@ void SysTick_Handler(void)
system_clock.Tick(); system_clock.Tick();
} }
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) // called with 1kHz (OPTIMIZE!) the display should get its own spi bus
{ {
if (htim != &htim2) { if (htim != &htim2) {
return; return;
@ -120,12 +120,19 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
static uint16_t count = 0; static uint16_t count = 0;
count++; count++;
if (count % (8000L / 20) == 0) { if (count % (1000L / 20) == 0) {
// refresh display with 20fps // refresh display with 20fps
ui.Flush(); ui.Flush();
count = 0; count = 0;
} }
static float v = 0;
dac1.WriteVoltage(0, v+= 0.1f);
dac1.WriteVoltage(1, v*3);
dac1.WriteVoltage(2, v*5);
dac1.WriteVoltage(3, v*10);
if(v > 1) v = -1;
// write audiodac1 // write audiodac1
// write audiodac2 // write audiodac2
// write audiodac3 // write audiodac3
@ -136,7 +143,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
void InitTimers(void) void InitTimers(void)
{ {
__HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_TIM2_CLK_ENABLE();
htim2.Init.Period = F_CPU / (8000 * 1) - 1; htim2.Init.Period = F_CPU / (1000 * 1) - 1;
htim2.Init.Prescaler = 0; htim2.Init.Prescaler = 0;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
@ -161,6 +168,7 @@ void Init(void)
//IWDG_Enable(); //IWDG_Enable();
display.Init(); display.Init();
encoder.Init(); encoder.Init();
dac1.Init();
InitTimers(); InitTimers();
} }