STM32 SPI Library for AD5235 Digital Potentiometer
Please read Liability Disclaimer and License Agreement CAREFULLY
AD5235 is a Dual 1024-Position Digital Potentiometer with Nonvolatile Memory that has the following features:
- Dual-channel, 1024-position resolution
- 25 kΩ, 250 kΩ nominal resistance
- Maximum ±8% nominal resistor tolerance error
- Low temperature coefficient: 35 ppm/°C
- 2.7 V to 5 V single supply or ±2.5 V dual supply
- SPI-compatible serial interface
- Nonvolatile memory stores wiper settings
- Power-on refreshed with EEMEM settings
- Permanent memory write protection
- Resistance tolerance stored in EEMEM
Please read AD5235 datasheet first.
This library is using SPI2 on a STM32 microcontroller, for a better understanding read this article DSLR Remote Control F7
AD5235.h
#ifndef __AD5235_H
#define __AD5235_H
#ifdef __cplusplus
extern "C" {
#endif
#include "spi.h"
#include "myDelay.h"
#define SEND_LIMIT 3
#define CMD_NOP 0x00 //0- Do nothing
//Control and Error Registers
#define EEMEM2RDAC 0x10 //1 - Restore EEMEM (A0) contents to RDAC (A0) register. See Table 16.
#define RDAC2EEMEM 0x20 //2 - Store wiper setting. Store RDAC (A0) setting to EEMEM (A0). See Table 15. - Use a delay of 50ms!!!
#define EEMEM_store 0x30 //3 - Store contents of Serial Register Data Byte 0 and Serial Register Data Bytes 1 (total 16 bits) to EEMEM (ADDR). See Table 18.- Use a delay of 50ms!!!/RDAC1 is 0, RDAC2 is 1, User1 is 2....User13 is 14
#define Down6Db 0x40 //4 - Decrement by 6 dB. Right-shift contents of RDAC (A0) register, stop at all 0s.
#define DownAll6Db 0x50 //5 - Decrement all by 6 dB. Right-shift contents of all RDAC registers, stop at all 0s.
#define Down1 0x60 //6 - Decrement contents of RDAC (A0) by 1, stop at all 0s.
#define Down1All 0x70 //7 - Decrement contents of all RDAC registers by 1, stop at all 0s.
#define AllRDAC 0x80 //8 - Reset. Refresh all RDACs with their corresponding EEMEM previously stored values. - Use a delay of 30us!!!
#define EEMEM_read 0x90 //9 - Read contents of EEMEM (ADDR) from SDO output in the next frame. See Table 19. - Use a delay of 30us!!!
#define gWiper 0xA0 //10 - Read RDAC wiper setting from SDO output in the next frame. See Table 20. - Use a delay of 30us!!!
#define sWiper 0xB0 //11 - Write contents of Serial Register Data Byte 0 and Serial Register Data Byte 1 (total 10 bits) to RDAC (A0). See Table 14.
#define Up6Db 0xC0 //12 - Increment by 6 dB: Left-shift contents of RDAC (A0),stop at all 1s. See Table 17.
#define UpAll6Db 0xD0 //13 - Increment all by 6 dB. Left-shift contents of all RDAC registers, stop at all 1s.
#define Up1 0xE0 //14 - Increment contents of RDAC (A0) by 1, stop at all 1s. See Table 15.
#define Up1All 0xF0 //15 - Increment contents of all RDAC registers by 1, stop at all 1s.
void storeEEMEM2RDAC(uint8_t w);
void storeRDAC2EEMEM(uint8_t w);
void setEEMEM(uint8_t w, uint16_t v);
void stepDown6Db(uint8_t w);
void stepDownAll6Db(void);
void stepDown1(uint8_t w);
void stepDown1All(void);
void refreshAllRDAC(void);
uint16_t getEEMEM(uint8_t w);
uint16_t getWiper(uint8_t w);
void setWiper(uint8_t w, uint16_t v);
void stepUp6Db(uint8_t w);
void stepUpAll6Db(void);
void stepUp1(uint8_t w);
void stepUp1All(void);
float getTolerance(void);
void repeatCMD(void);
#ifdef __cplusplus
}
#endif
#endif /* __AD5235_H */
AD5235.c
As example you can create in your gpio.h the following macros for a Chip Select pin set on PA8
#define ResistorOn HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
#define ResistorOff HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
#include "AD5235.h"
#include "spi.h"
#include "gpio.h"
uint16_t ret = 0;
static void AD5235_write(uint8_t cmd, uint16_t val){
uint8_t in[3] = {0, 0, 0};
in[0] = cmd;
in[1] = val >> 8;
in[2] = val & 0xFF;
ResistorOff;
HAL_SPI_Transmit(&hspi2, in, 3, 100);
ResistorOn;
}
static uint16_t AD5235_read(void){
uint8_t in[3] = {0, 0, 0};
uint8_t out[3] = {0, 0, 0};
ResistorOff;
HAL_SPI_TransmitReceive(&hspi2, in, out, 6, 100);
ResistorOn;
ret = (uint16_t)(out[1] << 8) + out[2];
return ret;
}
//uint16_t transferData(uint8_t cmd, uint16_t val)
//{
// uint8_t bytes[SEND_LIMIT], i;
// CS_PressOff;
// bytes[0] = cmd;
// bytes[1] = val >> 8;
// bytes[2] = val & 0xFF;
// __HAL_LOCK(&hspi2);
// for(i=0; i<SEND_LIMIT; i++)
// {
// // Wait until the transmit buffer is empty
// while(__HAL_SPI_GET_FLAG(&hspi2, SPI_FLAG_TXE) == RESET){
// }
// // Send the byte
// hspi2.Instance->DR = bytes[i];
// // Wait to receive a byte
// while(__HAL_SPI_GET_FLAG(&hspi2, SPI_FLAG_RXNE) != RESET){
// }
// // Return the byte read from the SPI bus
// bytes[i] = hspi2.Instance->DR;
// }
// __HAL_UNLOCK(&hspi2);
// CS_PressOn;
// return (uint16_t)(bytes[1] << 8) + bytes[2];
//}
void storeEEMEM2RDAC(uint8_t w) {
AD5235_write(EEMEM2RDAC + w, CMD_NOP);
} //1 - Restore EEMEM (A0) contents to RDAC (A0) register. See Table 16.
void storeRDAC2EEMEM(uint8_t w) {
AD5235_write(RDAC2EEMEM + w, CMD_NOP);
} //2 - Store wiper setting. Store RDAC (A0) setting to EEMEM (A0). See Table 15. - Use a delay of 50ms!!!
void setEEMEM(uint8_t w, uint16_t v) {
AD5235_write(EEMEM_store + w, v);
} //3 - Store contents of Serial Register Data Byte 0 and Serial Register Data Bytes 1 (total 16 bits) to EEMEM (ADDR). See Table 18.- Use a delay of 50ms!!!/RDAC1 is 0, RDAC2 is 1, User1 is 2....User13 is 14
void stepDown6Db(uint8_t w) {
AD5235_write(Down6Db + w, CMD_NOP);
} //4 - Decrement by 6 dB. Right-shift contents of RDAC (A0) register, stop at all 0s.
void stepDownAll6Db(void) {
AD5235_write(DownAll6Db , CMD_NOP);
} //5 - Decrement all by 6 dB. Right-shift contents of all RDAC registers, stop at all 0s.
void stepDown1(uint8_t w) {
AD5235_write(Down1 + w, CMD_NOP);
} //6 - Decrement contents of RDAC (A0) by 1, stop at all 0s.
void stepDown1All(void) {
AD5235_write(Down1All, CMD_NOP);
} //7 - Decrement contents of all RDAC registers by 1, stop at all 0s.
void refreshAllRDAC(void) {
AD5235_write(AllRDAC, CMD_NOP);
} //8 - Reset. Refresh all RDACs with their corresponding EEMEM previously stored values. - Use a delay of 30us!!!
uint16_t getEEMEM(uint8_t w) {
AD5235_write(EEMEM_read + w, CMD_NOP);
//delay_us(30);
HAL_Delay(1);
return AD5235_read();
}//9 - Read contents of EEMEM (ADDR) from SDO output in the next frame. See Table 19. - Use a delay of 30us!!!
uint16_t getWiper(uint8_t w) {
AD5235_write(gWiper + w, CMD_NOP);
//delay_us(30);
HAL_Delay(1);
return AD5235_read();
//transferData(0xA0 + w, CMD_NOP);
//HAL_Delay(1);
//return transferData(CMD_NOP, CMD_NOP);
} //10 - Read RDAC wiper setting from SDO output in the next frame. See Table 20. - Use a delay of 30us!!!
void setWiper(uint8_t w, uint16_t v) {
AD5235_write(sWiper + w, v);
//transferData(0xB0 + w, v);
} //11 - Write contents of Serial Register Data Byte 0 and Serial Register Data Byte 1 (total 10 bits) to RDAC (A0). See Table 14.
void stepUp6Db(uint8_t w) {
AD5235_write(Up6Db, CMD_NOP);
} //12 - Increment by 6 dB: Left-shift contents of RDAC (A0),stop at all 1s. See Table 17.
void stepUpAll6Db(void) {
AD5235_write(UpAll6Db, CMD_NOP);
} //13 - Increment all by 6 dB. Left-shift contents of all RDAC registers, stop at all 1s.
void stepUp1(uint8_t w) {
AD5235_write(Up1 + w, CMD_NOP);
}//14 - Increment contents of RDAC (A0) by 1, stop at all 1s. See Table 15.
void stepUp1All(void) {
AD5235_write(Up1All, CMD_NOP);
}//15 - Increment contents of all RDAC registers by 1, stop at all 1s.
void repeatCMD(void) {
ResistorOff;
ResistorOn;
}//16 - See page 21 in manual Another subtle feature of the AD5235 is that a subsequent CS strobe, without clock and data, repeats a previous command
float getTolerance(void)
{
float tol = getEEMEM(15);
int8_t b_1 = ((uint16_t)tol >> 8);
int8_t b_0 = ((uint16_t)tol & 0xFF);
if(b_1 > 127) //check if first bit in b_1 is 1
b_1 -= 128;
else
b_1 = -b_1;
for(uint8_t p = 0; p < 8; p++)
{
if((b_0 >> p) & 1)//check if but in position p is 1
{
tol =(float)b_1 + (float)b_0/ (float)(2 << p);//add the decimal part of the tolerance
break;
}
}
return tol;
}
Comments powered by CComment