Управление ЦАПом AD5761 с помощью контроллера STM32
- Войдите на сайт для отправки комментариев
Пнд, 10/12/2018 - 13:03
Здравствуйте, возникла такая проблема, не обновляется выход ЦАПа при работе с STM32. Однако при работе с Arduino nano все работает корректно. Код с Arduino был переделан под STM32, подскажите где допустил ошибку.
Ниже приведен код для Arduino и для STM32:
Arduino
#define CMD_NOP 0x0 #define CMD_WR_TO_INPUT_REG 0x1 #define CMD_UPDATE_DAC_REG 0x2 #define CMD_WR_UPDATE_DAC_REG 0x3 #define CMD_WR_CTRL_REG 0x4 #define CMD_NOP_ALT_1 0x5 #define CMD_NOP_ALT_2 0x6 #define CMD_SW_DATA_RESET 0x7 #define CMD_RESERVED 0x8 #define CMD_DIS_DAISY_CHAIN 0x9 #define CMD_RD_INPUT_REG 0xA #define CMD_RD_DAC_REG 0xB #define CMD_RD_CTRL_REG 0xC #define CMD_NOP_ALT_3 0xD #define CMD_NOP_ALT_4 0xE #define CMD_SW_FULL_RESET 0xF #include <SPI.h> // Include the Arduino SPI library const int ssPin = 10; static byte SPI_Buff[3]; // read data ??? void setup() { Serial.begin(9600); pinMode(ssPin, OUTPUT); // Set the SS pin as an output digitalWrite(ssPin, HIGH); // Set the SS pin HIGH SPI.begin(); // Begin SPI hardware SPI.setClockDivider(SPI_CLOCK_DIV64); // Slow down SPI clock SPI.setDataMode(SPI_MODE2); // software reset ad5761r_write(CMD_SW_FULL_RESET, 0); // read control register ad5761r_read(CMD_RD_CTRL_REG); ad5761r_read(CMD_RD_CTRL_REG); Serial.println("Readback from control register before setting:"); printRegisterData(); // write control register // [23:21][20][19:16] [15:11] [10:9] 8 7 6 5 [4:3] [2:0] // | | | | | | | | | | | | // X X X 0 0 1 0 0 X X X X X CV OVR B2C ETS IRO PV RA // // CV : Clear voltage selection 00=zero, 01=midscale, 10,11=full scale // OVR : 5% overrange 0=5% overrange disabled, 1=5% overrange enabled // B2C : Bipolar range 0=DAC input for bipolar range is straight binary coded // 1=DAC input for bipolar output range is twos complement code // ETS : Thermal shutdown alert 0=does not power down when die temperature exceeds 150degC // 1=powers down when die temperature exceeds 150degC // IRO : Internal reference 0=off, 1=on // PV : Power up voltage 00=zero scale, 01=midscale, 10,11=full scale // RA : Output range // 000=-10 to +10 // 001=0 to +10 // 010=-5 to +5 // 011=0 to +5 // 100=-2.5 to +7.5 // 101=-3 to +3 // 110=0 to +16 // 111=0 to +20 ad5761r_write(CMD_WR_CTRL_REG, 0b00000001000); // read control register ad5761r_read(CMD_RD_CTRL_REG); ad5761r_read(CMD_RD_CTRL_REG); Serial.println("Readback from control register after setting:"); printRegisterData(); } void printRegisterData() { Serial.print("CMD:"); Serial.print(SPI_Buff[0], HEX); Serial.print(" DATA:"); Serial.print(SPI_Buff[1], HEX); Serial.print(" "); Serial.println(SPI_Buff[2], HEX) ; } void loop() { ad5761r_write(CMD_WR_UPDATE_DAC_REG, 34000); delay(1); } void ad5761r_write(uint8_t reg_addr_cmd, uint16_t reg_data) { uint8_t data[3]; delay(1); digitalWrite(ssPin, LOW); delay(1); data[0] = reg_addr_cmd; data[1] = (reg_data & 0xFF00) >> 8; data[2] = (reg_data & 0x00FF) >> 0; for (int i=0; i<3; i++) { SPI.transfer(data[i]); } delay(1); digitalWrite(ssPin, HIGH); delay(1); } void ad5761r_read(uint8_t reg_addr_cmd) { delay(1); digitalWrite(ssPin, LOW); delay(1); SPI_Buff[0] = SPI.transfer(reg_addr_cmd); SPI_Buff[1] = SPI.transfer(0xFF); SPI_Buff[2] = SPI.transfer(0xFF); delay(1); digitalWrite(ssPin, HIGH); }
AD5761.h
#ifndef _AD5761_library_H #define _AD5761_library_H #define CMD_NOP 0x0 #define CMD_WR_TO_INPUT_REG 0x1 #define CMD_UPDATE_DAC_REG 0x2 #define CMD_WR_UPDATE_DAC_REG 0x3 #define CMD_WR_CTRL_REG 0x4 #define CMD_NOP_ALT_1 0x5 #define CMD_NOP_ALT_2 0x6 #define CMD_SW_DATA_RESET 0x7 #define CMD_RESERVED 0x8 #define CMD_DIS_DAISY_CHAIN 0x9 #define CMD_RD_INPUT_REG 0xA #define CMD_RD_DAC_REG 0xB #define CMD_RD_CTRL_REG 0xC #define CMD_NOP_ALT_3 0xD #define CMD_NOP_ALT_4 0xE #define CMD_SW_FULL_RESET 0xF #define AD5761_SPI &hspi1 #define AD5761_CS_SET() (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET)) #define AD5761_CS_RESET() (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET)) void ad5761_write(uint8_t reg_addr_cmd, uint16_t reg_data); void ad5761_writeVoltage(float voltage); void ad5761_beginDAC(void); #endif
AD5761.c
#include "stm32f1xx_hal.h" #include "gpio.h" #include "spi.h" #include "AD5761_library.h" #include "math.h" void ad5761_beginDAC(void){ ad5761_write(CMD_SW_FULL_RESET, 0); ad5761_write(CMD_WR_CTRL_REG, 0x8); } void ad5761_write(uint8_t reg_addr_cmd, uint16_t reg_data){ uint8_t data[3] = {0}; AD5761_CS_RESET(); AD5761_CS_SET(); data[0] = reg_addr_cmd; data[1] = (reg_data & 0x00FF) » 8; data[2] = (reg_data & 0xFF00) » 0; HAL_SPI_Transmit(AD5761_SPI, data, 3, 10); while(HAL_SPI_GetState(&hspi1)!= HAL_SPI_STATE_READY); AD5761_CS_RESET(); } void ad5761_writeVoltage(float voltage){ uint16_t outVoltage = ((voltage/2.5)/2)*pow(2,16); ad5761_write(CMD_WR_UPDATE_DAC_REG, outVoltage); }
///////////////////////////////////////////////////////
main.c
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); ad5761_beginDAC(); while (1) { ad5761_write(CMD_WR_UPDATE_DAC_REG, 4558); HAL_Delay(10); } }
STM32 поддерживается ArduinoIDE. так что вы можете взять код для Нано и почти ничего не меняя, скомпилировать его под СТМ32
Хотя я сомневаюсь. что ваш код под Нано работает -я не вижу где в нем обновление данных. Вы в ЛУП только пишете в АЦП. а обратно ничего не читаете
Так это не АЦП, а ЦАП вроде как. Читать из него смысла особого нет.
Вы наверное оговорились, это ЦАП, а не АЦП, поэтому ничего принимать мне от него не требуется. Код рабочий это 100%, я замерял выход мультиметром). По дата шиту ЦАПа первые 8 бит из 24 отвечают за его конфигурацию, именно они обновляют выход микросхемы.
Так это не АЦП, а ЦАП вроде как. Читать из него смысла особого нет.
да, сорри, неправильно прочитал вопрос - думал "не обновляются данные с АЦП" :)
ТС - попробуйте скетч для Ардуино Нано скопилировать под СТМ32 в среде Ардуино. В вашем коде вроде нет ничего такого, что требовало бы низкоуровневого программирования для СТМ
Я пытаюсь освоить STM32, пока, что пошел простым путем с использованием куба, так что ArduinoIDE не вариант.
Забыл упомянуть, что выход микросхемы всегда -10В (при работе с stm)
Я пытаюсь освоить STM32, пока, что пошел простым путем с использованием куба, так что ArduinoIDE не вариант.
Думаю, проблема в иннициализации шины SPI.
К сожалению, я тоже только начинаю осваивать стм32 в кубе. так что единственное, что могу посоветовать - прежде чем работать с неизвестной микросхемой, попробуйте для начала найти в сети любой пример работы с шиной SPI и убедится. что у вас на вашей плате он воспроизводится.
Я пытаюсь освоить STM32, пока, что пошел простым путем с использованием куба, так что ArduinoIDE не вариант.
Хотите пользоваться кубом вместе с ардуиновскими библиотеками - не забывайте инициализировать этим самым кубом все то, что по умолчанию инициализирует Arduino.
ну во первых писать в ардуино в перемешку с HAL прям какой то когнитивный диссонанс вызывет
обычно если пытаться сесть попой на два стула, то падаешь между ними .
а по делу : если файл Arduino у вас рабочий а файл AD5761.c это библиотека ктороую вы пытаетесь прикрутить
то между ними есть разница : в файле Arduino в строчке 106 ,вы пин SS только притягиваете к '0' , в файле же AD5761.c в той же функции в строчках 17-18.вы делаете CS_RESET а потом CS_SET и ваш DAC просто не реагирует на команды .
и точно ли класс SPI в Ардуино по умолчанию заведен на SPI1 ?
ну во первых писать в ардуино в перемешку с HAL прям какой то когнитивный диссонанс вызывет
насколько я понял ТС, он как раз "вперемешку" ничего не пишет. В его вопросе два разных кода - сначала идет рабочий код для Ардуино Нано. а потом - попытка ТС перенести этот код в Куб для СТМ32
точно, хотя к вопросу ТС это отношения не имеет :)
точно, хотя к вопросу ТС это отношения не имеет :)
если по умолчанию(я не знаю,не проверял) класс SPI в ардуино заведен на SPI2 a ТС в библиотеке AD5761 настроил SPI1,а DAC физически подсоединен к SPI2. ничего же работать небудет..
еще вопрос к ТС : как насторен SPI1 в файле AD5761.c ? частота spi_clk , размер фрейма ,endianess данных соответствует тому что указано на datasheet AD5761 ?
и еще ,судя по defines в файле AD5761.c CS_RESET у вас выставляет '1' а CS_SET выставляет '0' ,это для того что бы кого то запутать ?
если по умолчанию(я не знаю,не проверял) класс SPI в ардуино заведен на SPI2
по умолчанию в stm32duino класс SPI заведен на SPI1. Это абсолютно точно, можете даже не проверять. Я тут недавно 4 дня потратил на то, чтоб заставить на Блюпилл работать по SPI одновременно TFT экран, тачскрин и RFID :) - так что в нюансах SPI в стм32дуино я покопался основательно :)
В кубе инициализировал все правильно, не забыл. SCLK настроен на максимально частоту - 18Mhz, один пакет передает 8 бит. Сначала передается MSB.
Мне так удобнее было) Никого запутать не хотел.
В кубе инициализировал все правильно, не забыл. SCLK настроен на максимально частоту - 18Mhz
а микросхема ЦАП такую скорость тянет?
кстати, если это stm32f103. то макисимум для SPI1 на ней 36 МГц
Судя по дата шиту он тянет до 50Mhz. Да это именно она, странно, но куб мне не дал выставить делитель меньше 4.
https://www.st.com/resource/en/datasheet/cd00161566.pdf страница 71.
SPI clock frequency Master mode/Slave mode - 18 MHz
мне кажеться или когда
data[1] и data[2] при любом reg_data будут = 0 ?
мне кажеться или когда
data[1] и data[2] при любом reg_data будут = 0 ?
да. похоже :)
В исходном коде, кстати, правильно :)
Не заметил, что перенес неправильно. Сейчас переделаю и проверю.
Всем спасибо, всё заработало! Невнимательность)