之前寫過了mcu通過硬體spi介面向dac芯片ad5764的資料暫存器寫值輸出電壓,ad5764的offset與gain暫存器的值也是可以通過硬體spi讀出來的,
第一步:將待讀取的芯片設定為讀模式

回讀的命令定義如下:

當要回讀時,應向輸入移位暫存器寫入0x010000,因為要將REG2、REG1、REG0全部設定為0,將A2、A1設定為0,將A0設定為1,同時將DB0設定為0;
第二步與第三步:

可以看到在時序圖中,回讀發生了2次資料發送(spi是同步通信,發送幾次意味著接收幾次),第一次發送向芯片寫入命令,告訴芯片準備讀哪個通道的哪個暫存器,回傳的資料是未定義的,可以不用管;第二次發送NOP,接收芯片回傳的暫存器的值,
接下來就是撰寫代碼實作功能了,因為板子上有2顆ad5762與2顆ad5764,還是需要使用徑訓鏈通信,
資料定義:
//REGISTER MAP
#define AD5764_NOP 0x000000
#define READ 0x800000
#define WRITE 0x000000
#define REG_FUNCTION 0x000000
#define REG_DATA 0x100000
#define REG_COARSE_GAIN 0x180000
#define REG_FINE_GAIN 0x200000
#define REG_OFFSET 0x280000
#define DAC_A 0x000000
#define DAC_B 0x010000
#define DAC_C 0x020000
#define DAC_D 0x030000
#define DAC_ALL 0x040000
#define SDO_ENABLE 0x000000
#define SDO_DISABLE 0x000001
enum lcc_ch_num{
ch1 = 1, ch2, ch3, ch4, ch5, ch6
};
enum lcc_ch_abcd{
a = 1, b, c, d
};
typedef struct DAC_SEND_ARRAY
{
uint32_t send_array[4];//AB
uint32_t send_cd_array[4];//CD
uint32_t receive_array[4];
}ad_5764_spi;
spi讀寫函式的實作程序,細講
//spi讀寫函式的實作程序在之前的博文中
void hw_spi_read_write(uint32_t *send_data, uint32_t *receice_data, uint8_t size)
{
SPI_SET_SS0_LOW(SPI1);
for (uint8_t i = 0; i < size; i++)
{
SPI_WRITE_TX0(SPI1, send_data[i]);
SPI_TRIGGER(SPI1);
while (SPI_IS_BUSY(SPI1));
receice_data[i] = SPI_READ_RX0(SPI1);
}
SPI_SET_SS0_HIGH(SPI1);
LDAC = PIN_LOW;
Delay(1);
LDAC = PIN_HIGH;
}
void daisy_chain_readregister(enum lcc_ch_num ch, enum lcc_ch_abcd abcd, uint32_t RegisterSelect)
{
memset(spi_ad5764.send_array, 0, sizeof(spi_ad5764.send_array));
// 設定ad5764為讀模式
if (ch == ch1)
{
spi_ad5764.send_array[3] = 0x010000;
}
else if (ch == ch2)
{
spi_ad5764.send_array[2] = 0x010000;
}
else if (ch == ch3 || ch == ch4)
{
spi_ad5764.send_array[1] = 0x010000;
}
else if (ch == ch5 || ch == ch6)
{
spi_ad5764.send_array[0] = 0x010000;
}
hw_spi_read_write(spi_ad5764.send_array, spi_ad5764.receive_array, 4);
switch (ch)
{
case ch1:
if (abcd == a)
{
spi_ad5764.send_array[3] = READ + RegisterSelect + DAC_A;
}
else if (abcd == b)
{
spi_ad5764.send_array[3] = READ + RegisterSelect + DAC_B;
}
break;
case ch2:
if (abcd == a)
{
spi_ad5764.send_array[2] = READ + RegisterSelect + DAC_A;
}
else if (abcd == b)
{
spi_ad5764.send_array[2] = READ + RegisterSelect + DAC_B;
}
break;
case ch3:
if (abcd == a)
{
spi_ad5764.send_array[1] = READ + RegisterSelect + DAC_A;
}
else if (abcd == b)
{
spi_ad5764.send_array[1] = READ + RegisterSelect + DAC_B;
}
break;
case ch4:
if (abcd == c)
{
spi_ad5764.send_array[1] = READ + RegisterSelect + DAC_C;
}
else if (abcd == d)
{
spi_ad5764.send_array[1] = READ + RegisterSelect + DAC_D;
}
break;
case ch5:
if (abcd == a)
{
spi_ad5764.send_array[0] = READ + RegisterSelect + DAC_A;
}
else if (abcd == b)
{
spi_ad5764.send_array[0] = READ + RegisterSelect + DAC_B;
}
break;
case ch6:
if (abcd == c)
{
spi_ad5764.send_array[0] = READ + RegisterSelect + DAC_C;
}
else if (abcd == d)
{
spi_ad5764.send_array[0] = READ + RegisterSelect + DAC_D;
}
break;
default:
break;
}
//發送讀哪個暫存器和哪個通道
hw_spi_read_write(spi_ad5764.send_array, spi_ad5764.receive_array, 4);
memset(spi_ad5764.send_array, 0, sizeof(spi_ad5764.send_array));
memset(spi_ad5764.receive_array, 0, sizeof(spi_ad5764.receive_array));
for (uint8_t i = 0; i < 4; i++)
{
spi_ad5764.send_array[i] = AD5764_NOP;
}
//發送接收命令
hw_spi_read_write(spi_ad5764.send_array, spi_ad5764.receive_array, 4);
}
至此回讀功能就實作了,在測驗程序中發現,在設定為讀模式回讀暫存器值之后,如果要向資料暫存器寫入值輸出電壓,直接使用寫命令即可,無需將芯片設定為寫模式;另外我使用NUC123SD4AN0的SPI1介面可以將時鐘設定為16MHz,寫命令是正常的,但是回讀的時候,每次都少了2個bit(第0位和第1位),當我把SPI的時鐘降低為8MHz時,回讀會少1個bit(第0位),當把時鐘降低為4MHz時,回讀的資料才正確無誤了,不知為何,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/233953.html
標籤:其他
