AD5592R STM32驱动代码
作者:互联网
一、前言
最近项目上需要使用8路DAC,本来想用STM32自带的DAC,但是STM32自带的DAC好像只有2路,不满足要求,市面上很多的DAC芯片虽然有8路,但是精度只有8位,而我需要一个精度更高的,在选型的时候选到了ADS9226这款芯片,它有8个DAC通道,精度是12位的,当时也只关心这2个指标。
等到使用的时候才发现这个芯片的功能比想象中的更强大,它的每个通道都可以配置为:ADC、DAC、GPIO输入、GPIO输出、85kΩ下拉、开漏、三态,可以配置的功能非常多,然鹅让我没想到的是网上竟然找不到现成的程序可以参考,于是我自己写了一个STM32的测试程序。
手册去ADI的官网可以找到,中文的和英文的都有,但是要注意的是中文手册有点问题,目前发现有些寄存器的地址号写的不对,但是英文手册写的没问题。
我因为只使用DAC功能,因此我只测试了DAC功能,ad5592r.c里面有一个DAC的例程,经过测试是没问题的。下面我附上ad5592r.c和ad5592r.h,这两个文件配合正点原子的库函数版本使用,拿SPI的例程改改就能用。但是SPI初始化函数需要改改,一个是SPI的数据为16位的,一个是第一个边沿采样。代码如下,需要注意的地方我给标红了。
1 void SPI2_Init(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 SPI_InitTypeDef SPI_InitStructure; 5 6 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 7 RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 8 9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; 10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 11 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 12 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB 13 14 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; 15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PB13/14/15复用推挽输出 16 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB 17 18 19 GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉 20 21 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 22 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI 23 SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //设置SPI的数据大小:SPI发送接收16位帧结构 24 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 25 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 26 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 27 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //定义波特率预分频的值:波特率预分频值为256 28 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 29 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 30 SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 31 32 SPI_Cmd(SPI2, ENABLE); //使能SPI外设 33 34 //SPI2_ReadWriteByte(0xff);//启动传输 35 }
ad5592r.c
1 #include "ad5592r.h" 2 #include "spi.h" 3 #include "delay.h" 4 #include "usart.h" 5 6 /** 7 * /brief 初始化AD5592R 8 */ 9 void AD5592R_Init(void) 10 { 11 GPIO_InitTypeDef GPIO_InitStructure; 12 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 13 14 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PB12 推挽 15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 16 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 17 GPIO_SetBits(GPIOB,GPIO_Pin_12); 18 GPIO_Init(GPIOB, &GPIO_InitStructure); 19 20 //PB11与AD5592R RESET引脚连接 21 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; // PB11 推挽 22 GPIO_SetBits(GPIOB, GPIO_Pin_11); 23 GPIO_Init(GPIOB, &GPIO_InitStructure); 24 25 SPI2_Init(); //初始化SPI 26 SPI2_SetSpeed(SPI_BaudRatePrescaler_32); //设置为256分频 27 28 AD5592R_HW_Reset(); 29 } 30 31 /** 32 * \brief AD5592R硬件复位 33 */ 34 void AD5592R_HW_Reset(void) 35 { 36 GPIO_ResetBits(GPIOB, GPIO_Pin_11); 37 delay_us(250); //手册上说复位功能最多需要250us 38 GPIO_SetBits(GPIOB, GPIO_Pin_11); 39 } 40 41 /** 42 * \brief 读取AD5592R的寄存器 43 * 44 * \param[in] addr:寄存器地址 45 * 46 * \note D1和D0用来选择LDAC模式,每当调用一次该函数时,都会将模式设定为DAC即时更 47 * 新模式,需要修改的话,可以用一个变量保存。 48 */ 49 u16 AD5592R_Read_Register(ad5592r_addr_t addr) 50 { 51 u16 data = 0; 52 53 data = (RDBK_LDAC_MODE << 11) | RDBK_LDAC_MODE_EN | (addr << 2); //选择寄存器,使能回读并设定回读寄存器地址 54 55 AD5592R_CS=0; //使能器件 56 SPI2_ReadWriteByte(data); //发送读取状态寄存器命令 57 AD5592R_CS=1; 58 59 delay_us(1); //片选信号拉低到拉高之间的时间间隔最小为20nS 60 61 AD5592R_CS=0; 62 data = SPI2_ReadWriteByte(0X0000); //读取一个字节 63 //delay_us(1); //如果上一行发送的数据是0xFFFF,那么片选信号很快就会拉高,但是发其他数据却不会,原因不明,因此这里加一个延时。 64 AD5592R_CS=1; //取消片选 65 66 return data; 67 } 68 69 70 /** 71 * \brief 读取AD5592R的寄存器 72 * 73 * \note 这个函数主要是用来测试,读出来15个寄存器的值。芯片复位后读取,其中data[6]为0x00FF,data[7]为0x005C,其他寄存器的值都为0,如果读出的结果都为0xFFFF,那可能通信出现问题了 74 */ 75 void AD5592R_Read_All_Register(u16 data[16]) 76 { 77 u8 i; 78 79 for (i = 0; i < 16; i++) { 80 data[i] = AD5592R_Read_Register((ad5592r_addr_t)i); 81 } 82 } 83 84 /** 85 * \brief 通用控制寄存器配置 86 * 87 * \param[in] flag:可以加入如下标志: 88 * #GP_COTL_ADC_BUF_PRECHARGE: ADC缓冲器用于对ADC预充电,不设置则禁用(默认) 89 * #GP_COTL_ADC_BUF_EN: 使能ADC缓冲器,不设置则禁能(默认) 90 * #GP_COTL_LOCK: 不能改变I/Ox引脚配置寄存器的内容,不设置则可以改变(默认) 91 * #GP_COTL_ALL_DAC: (一个数据)写入所有DAC,不设置则由DAC地址决定写入哪个DAC(默认) 92 * #GP_COTL_ADC_RANGE_REFx2: ADC增益为0 V至2 × VREF,不设置则为1倍(默认) 93 * #GP_COTL_DAC_RANGE_REFx2: DAC增益为0 V至2 × VREF,不设置则为1倍(默认) 94 */ 95 void AD5592R_GP_Contol_Set(u16 flag) 96 { 97 u16 data = 0; 98 99 data = (GP_CNTL_REG << 11) | flag; 100 AD5592R_CS = 0; 101 SPI2_ReadWriteByte(data); 102 AD5592R_CS = 1; 103 } 104 105 /** 106 * \brief 将指定的引脚配置为指定的功能 107 * 108 * \param[in] func:设定的功能#ADC_PIN_CONF:配置为ADC引脚 109 * #DAC_PIN_CONF:配置为DAC引脚 110 * #PD_CONF:下拉配置,设定为85kΩ下拉(默认就是这个) 111 * #GPIO_W_CONF:GPIO写配置,意思就是将引脚配置为GPIO输出 112 * #GPIO_R_CONF:GPIO读配置,意思就是将引脚配置为GPIO输入 113 * #GPIO_OD_CONF:GPIO开漏配置,意思就是将引脚配置为开漏输出,否则为推挽输出(默认) 114 * #GPIO_3_STAT_CONF:三态配置 115 * \param[in] pin:选择需要配置的引脚,取值为AD5592R_PIN_0~AD5592R_PIN_7,可以按 116 * 位或。 117 * 118 * 119 * \param[in] flag:根据func的值,可以传入一些特殊标志,具体如下: 120 * 1、如果写入的func值为 GPIO_W_CONF,则传入的flag可以加入 121 * AD5592R_PIN_7_BUSY,表示将PIN7设定为BUSY引脚。 122 * 2、如果写入的func值为GPIO_R_CONF,则传入的flag可以加入 123 * GPIO_R_CONF_EN_RDBK,表示下一个SPI操作输出GPIO引脚的状态, 124 * 并将状态通过返回值返回。 125 * 126 * 127 */ 128 u8 AD5592R_Pin_Config(ad5592r_addr_t func, u8 pin, u16 flag) 129 { 130 u16 data = 0; 131 132 //将PIN_7设定为BUSY引脚,如果传入AD5592R_PIN_7_BUSY,那么D7也必须为1 133 if ((func == GPIO_W_CONF) && (flag & AD5592R_PIN_7_BUSY)) { 134 data |= AD5592R_PIN_7; 135 } 136 137 if ((func == GPIO_W_CONF) && (flag & GPIO_R_CONF_EN_RDBK)) { 138 data |= GPIO_R_CONF_EN_RDBK; 139 } 140 141 data |= (func << 11) | pin; 142 143 AD5592R_CS = 0; 144 SPI2_ReadWriteByte(data); 145 AD5592R_CS = 1; 146 //如果使能GPIO回读,那么下一个SPI操作返回GPIO引脚的状态 147 if ((func == GPIO_W_CONF) && (flag & GPIO_R_CONF_EN_RDBK)) { 148 delay_us(1); 149 AD5592R_CS = 0; 150 data = SPI2_ReadWriteByte(0); 151 AD5592R_CS = 1; 152 return data; 153 } 154 155 return 0; 156 } 157 158 /** 159 * \brief 给8个GPIO写入数据 160 * 161 * \param[in] value:要写入的值 162 */ 163 void AD5592R_GPIO_Write(u8 value) 164 { 165 u16 data = (GPIO_W_DATA << 11) | value; 166 167 AD5592R_CS = 0; 168 SPI2_ReadWriteByte(data); 169 AD5592R_CS = 1; 170 } 171 172 /** 173 * \brief 给DAC通道写入数据 174 * 175 * \param[in] channel:0~7有效,指定DAC通道 176 * \param[in] value:要写入的值,低12位有效 177 */ 178 void AD5592R_DAC_Write_Data(u8 channel, u16 value) 179 { 180 u16 data = 0; 181 182 channel &= 0x07; //只取低3位 183 value &= 0x0FFF; //只取低12位 184 185 data = (1 <<15) | (channel << 12) | value; //最高位要置1,表示写数据 186 187 AD5592R_CS = 0; 188 SPI2_ReadWriteByte(data); 189 AD5592R_CS = 1; 190 } 191 192 /** 193 * \brief 配置DAC通道回读 194 * 195 * \param[in] channel:0~7有效,指定DAC通道 196 * \param[in] value:要写入的值,低12位有效 197 * 198 * \note 指的是当某个DAC通道使能以后,每次使能回读之后的下一个时钟周期读出数据 199 * 并不是每次写DAC数据后的下一个时钟周期读出数据 200 */ 201 u16 AD5592R_DAC_Readback(u8 channel) 202 { 203 u16 data = 0; 204 205 channel &= 0x07; //只取低3位 206 data = (DAC_READBACK << 11) | (0x3 << 3) | channel; 207 AD5592R_CS = 0; 208 SPI2_ReadWriteByte(data); 209 AD5592R_CS = 1; 210 delay_us(1); 211 AD5592R_CS = 0; 212 data = SPI2_ReadWriteByte(0); 213 AD5592R_CS = 0; 214 215 data &= 0xFFF; //取低12位,事实上读取成功后,最高位是1,以表示这是一个数据 216 return data; 217 } 218 219 /** 220 * \brief 设定关断DAC和内部基准电压源 221 * 222 * \param[in] value:#true:关断基准电压源、 DAC和ADC 223 * #false:基准电压源和DAC关断状态由D9和D7至D0决定(默认)。 224 */ 225 void AD5592R_PD_ALL_Set(u8 value) 226 { 227 u16 data = 0; 228 229 data = AD5592R_Read_Register(POW_DOWN_REF_CNTL); //先读出寄存器的值 230 231 data |= (POW_DOWN_REF_CNTL << 11); 232 233 if (value == false) { 234 data &= ~POW_DOWN_REF_CNTL_PD_ALL; 235 } else { 236 data |= POW_DOWN_REF_CNTL_PD_ALL; 237 } 238 239 AD5592R_CS = 0; 240 SPI2_ReadWriteByte(data); 241 AD5592R_CS = 1; 242 } 243 244 /** 245 * \brief 选择基准电压源 246 * 247 * \param[in] value: #REF_INTERNAL:使用内部基准电压源 248 * #REF_EXTERNAL:使用外部基准电压源 249 */ 250 void AD5592R_Ref_Set(ref_select_t value) 251 { 252 u16 data = 0; 253 254 data = AD5592R_Read_Register(POW_DOWN_REF_CNTL); //先读出寄存器的值 255 256 data |= (POW_DOWN_REF_CNTL << 11); 257 258 if (value == REF_INTERNAL) { 259 data &= ~POW_DOWN_REF_CNTL_EN_REF; 260 } else { 261 data |= POW_DOWN_REF_CNTL_EN_REF; 262 } 263 264 AD5592R_CS = 0; 265 SPI2_ReadWriteByte(data); 266 AD5592R_CS = 1; 267 } 268 269 /** 270 * \brief 选择关断DAC 271 * 272 * \param[in] pin:选择需要配置的引脚,取值为AD5592R_PIN_0~AD5592R_PIN_7,可以按 273 * 位或。 274 * \param[in] mode: #MORMAL_MODE:选择的引脚设置为正常模式 275 * #PD_MODE:引脚若配置为DAC则关断 276 */ 277 void AD5592R_PD_DAC(u8 pin, pd_mode_t mode) 278 { 279 u16 data = 0; 280 281 data = AD5592R_Read_Register(POW_DOWN_REF_CNTL); //先读出寄存器的值 282 data |= (POW_DOWN_REF_CNTL << 11); 283 if (mode == MORMAL_MODE) { 284 data &= ~pin; 285 } else { 286 data |= pin; 287 } 288 AD5592R_CS = 0; 289 SPI2_ReadWriteByte(data); 290 AD5592R_CS = 1; 291 } 292 293 /** 294 * \brief ADC序列寄存器设置 295 * 296 * \prarm[in] channel:0~7有效,指定需要加入转换序列的ADC通道 297 * \prarm[in] flag:可以加入如下标志: 298 * #ADC_SEQ_REP:使能序列重复,不设置则禁用序列重复(默认) 299 * #ADC_SEQ_TEMP:使能温度指示器回读,不设置则禁用温度指示器回读(默认) 300 */ 301 void AD5592R_ADC_Sequence_set(u8 channel, u16 flag) 302 { 303 u16 data = 0; 304 305 channel &= 0x07; 306 307 data = (ADC_SEQ_REG << 11) | flag | channel; 308 AD5592R_CS = 0; 309 SPI2_ReadWriteByte(data); 310 AD5592R_CS = 1; 311 } 312 313 314 /** 315 * \brief AD5592R软件复位 316 */ 317 void AD5592R_Soft_Reset(void) 318 { 319 AD5592R_CS = 0; 320 SPI2_ReadWriteByte(0x7DAC); //SPI写入0x7DAC表示软件复位 321 AD5592R_CS = 1; 322 } 323 324 325 #if 0 326 int main(void) 327 { 328 u8 i = 0; 329 u16 data[16] = { 0 }; 330 u16 value = 0; 331 332 delay_init(); //延时函数初始化 333 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 334 uart_init(115200); //串口初始化为115200 335 printf("Hello World!\r\n"); 336 LED_Init(); //初始化与LED连接的硬件接口 337 338 AD5592R_Init(); 339 //AD5592R_Read_All_Register(data); 340 //for (i = 0; i < 16; i++) { 341 // printf("data[%d] = 0x%04x\r\n", i, data[i]); 342 //} 343 344 AD5592R_Ref_Set(REF_EXTERNAL); //DAC使用外部基准源 345 AD5592R_Pin_Config(DAC_PIN_CONF, AD5592R_PIN_ALL, 0); //将所有引脚配置为DAC 346 AD5592R_DAC_Write_Data(0, 0x888); 347 value = AD5592R_DAC_Readback(0); 348 printf("value = 0x%04x\r\n", value); 349 350 while(1) 351 { 352 delay_ms(500); 353 delay_ms(500); 354 LED0=!LED0;//DS0闪烁 355 } 356 } 357 #endif
ad5592r.h
1 /** 2 * \brief AD5592R的寄存器和数据都是16位的 3 * SYNC引脚在16位数据传输开始之前拉低,16位数据传输完成之后拉高 4 * 高位先传 5 * 空闲时时钟为高电平 6 * 写入DAC时,数据能够以最高50 MHz的速率传输。执行转换或从AD5592R传输数据时, SCLK的最大速度为20 MHz。 7 * 对于AD5592R来说,在时钟的下降沿读取数据,时钟上升沿发送数据,也就是说 8 * 主机应该配置为下降沿发送,上升沿读取 9 * 片选信号拉低到拉高之间的时间间隔最小为30nS 10 */ 11 12 #ifndef __AD5592R_H 13 #define __AD5592R_H 14 #include "sys.h" 15 16 /** 17 * \brief STM32引脚定义 18 * @{ 19 */ 20 #define AD5592R_CS PBout(12) //AD5592R的片选信号 21 /** 22 * @} 23 */ 24 25 /** 26 * \brief AD5592R引脚定义 27 * @{ 28 */ 29 #define AD5592R_PIN_0 (1 << 0) 30 #define AD5592R_PIN_1 (1 << 1) 31 #define AD5592R_PIN_2 (1 << 2) 32 #define AD5592R_PIN_3 (1 << 3) 33 #define AD5592R_PIN_4 (1 << 4) 34 #define AD5592R_PIN_5 (1 << 5) 35 #define AD5592R_PIN_6 (1 << 6) 36 #define AD5592R_PIN_7 (1 << 7) 37 #define AD5592R_PIN_ALL 0xFF 38 39 #define AD5592R_PIN_7_BUSY (1 << 8) 40 #define GPIO_R_CONF_EN_RDBK (1 << 10) 41 /** 42 * @} 43 */ 44 45 #ifndef true 46 #define true 1 47 #endif 48 49 #ifndef false 50 #define false 0 51 #endif 52 53 typedef enum ref_select { 54 REF_INTERNAL = 0, /* 使用内部基准电压源 */ 55 REF_EXTERNAL = 1, /* 使用外部基准电压源 */ 56 } ref_select_t; 57 58 typedef enum pd_mode { 59 MORMAL_MODE = 0, /* 选择的引脚设置为正常模式 */ 60 PD_MODE = 1, /* 通道若配置为DAC则关断 */ 61 } pd_mode_t; 62 63 /** 64 * \brief 定义AD5592R的寄存器地址 65 */ 66 typedef enum ad5592r_addr { 67 NOP = 0, //无操作 68 DAC_READBACK = 1, //DAC回读寄存器 69 ADC_SEQ_REG = 2, //ADC序列寄存器 70 GP_CNTL_REG = 3, //通用控制寄存器 71 ADC_PIN_CONF = 4, //ADC引脚配置 72 DAC_PIN_CONF = 5, //DAC引脚配置 73 PULL_DOWN_CONF = 6, //下拉配置 74 RDBK_LDAC_MODE = 7, //回读和LDAC模式 75 GPIO_W_CONF = 8, //GPIO写配置 76 GPIO_W_DATA = 9, //GPIO写数据 77 GPIO_R_CONF = 10, //GPIO读配置 78 POW_DOWN_REF_CNTL = 11, //断电/基准控制 79 GPIO_OD_CONF = 12, //GPIO开漏配置 80 GPIO_3_STAT_CONF = 13, //三态配置 81 RESERV = 14, //保留 82 SOFT_REST = 15, //软件复位 83 } ad5592r_addr_t; 84 85 /** 86 * \brief 寄存器定义 87 * @{ 88 */ 89 90 /** 91 * \brief 输入移位寄存器 92 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 93 * |D15|D14|D13|D12|D11|D10|D9 |D8 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | 94 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 95 * | 0 | 控制寄存器地址| 0 | 0 | 控制寄存器数据 | 96 * +---+-----------+---+---+---+-----------------------------------+ 97 * | 1 | DAC地址 | 12位DAC数据 | 98 * +---+-----------+-----------------------------------------------+ 99 * 控制寄存器应该写入的数据格式见各个具体寄存器的描述 100 * @{ 101 */ 102 #define CNTL_BIT (0 << 15) //表示控制寄存器 103 #define DATA_BIT (1 << 15) //表示数据寄存器 104 //当D15为1时,[D14:D12]对应DAC通道,[D11:D0]表示DAC数据 105 106 /** 107 * \brief 以下定义为控制地址定义,当B15为0时有效 108 * @{ 109 */ 110 #define CNTL_ADDR_NOP (0 << 11) //无操作 111 112 /** 113 * \brief DAC回读寄存器,[D15:D5]固定为 0000 1000 000,[D4:D3]为11表示使能回读,为00表示禁能回读(默认),[D2:D0]选择DAC通道 114 * 当使能了DAC回读,那么给DAC通道写入数据并且SYNC引脚拉高之后,将SYNC拉低并发送16个时钟就能从SDO引脚读到回读的值。 115 */ 116 #define CNTL_ADDR_DAC_READBACK (1 << 11) //DAC回读 117 118 /** 119 * \brief ADC序列寄存器,[D15:D10]固定为 0001 00,[D7:D0]某一位为1则该ADC通道在转换序列中 120 */ 121 //ADC转换结果,D15为0,[D14:D12]指定ADC通道,[D11:D0]表示转换后的结果 122 #define CNTL_ADDR_ADC_SEQ_REG (2 << 11) //ADC序列寄存器,选择ADC(s)进行转换 123 #define ADC_SEQ_REP (1 << 9) //#0:ADC序列重复禁能(默认)。#1:ADC序列重复使能 124 #define ADC_SEQ_TEMP (1 << 10) //#0:禁用温度指示器回读(默认)。#1:启用温度指示器回读 125 126 #define CNTL_ADDR_GP_CNTL_REG (3 << 11) //通用控制寄存器,ADC和DAC控制寄存器 127 128 /** 129 * \brief ADC引脚配置寄存器,[D15:D8]固定为 0010 0000,[D7:D0]哪一位为1则设定哪个引脚为ADC引脚,如果设置为0(默认), 130 * 则输入输出功能由引脚配置寄存器决定 131 */ 132 #define CNTL_ADDR_ADC_PIN_CONF (4 << 11) //ADC引脚配置,选择哪些引脚是ADC输入 133 134 /** 135 * \brief DAC引脚配置寄存器,[D15:D8]固定为0010 1000,[D7:D0]哪一位为1则设定哪个引脚为DAC引脚,如果设置为0(默认), 136 * 则输入输出功能由引脚配置寄存器决定 137 */ 138 #define CNTL_ADDR_DAC_PIN_CONF (5 << 11) //DAC引脚配置,选择哪些引脚是DAC输出 139 140 /** 141 * \brief 下拉配置寄存器,[D15:D8]固定为0011 0000,[D7:D0]:#0:输入/输出功能由引脚配置寄存器决定。#1:该引脚为85kΩ下拉 142 */ 143 #define CNTL_ADDR_PD_CONF (6 << 11) //下拉配置,选择哪些引脚具有85kΩ下拉电阻到GND 144 145 /** 146 * \brief 回读和LDAC模式寄存器,[D15:D7]固定为0011 1000 0, 147 * [D5:D2]指定要回读的寄存器地址,读取寄存器的值通过该指令 148 * [D1:D0]确定如何处理写入DAC输入寄存器的数据: 149 * #00:写入输入寄存器的数据立即复制到DAC寄存器,DAC输出更新(默认) 150 * #01:写入输入寄存器的数据不会复制到DAC寄存器,DAC输出不更新 151 * #10:写入输入寄存器的数据复制到相应的DAC寄存器,数据传输后DAC输出同时更新 152 */ 153 #define CNTL_ADDR_RDBK_LDAC_MODE (7 << 11) //回读和LDAC模式,选择加载DAC(LDAC)功能的操作和/或回读哪个配置寄存器 154 #define RDBK_LDAC_MODE_EN (1 << 6) //#0:未启用回读。#1:[D5:D2]选择要回读的寄存器,读取结束后D6自动清除 155 #define RDBK_LDAC_MODE_IMMDEDIATELY (0 << 0) //立即更新 156 #define RDBK_LDAC_MODE_NOT (1 << 0) //不更新 157 #define RDBK_LDAC_MODE_AFTER (2 << 0) //数据传输后更新 158 159 /** 160 * \brief GPIO写配置寄存器,[D15:D9]固定为0100 000,D8描述见下,[D7:D0]某位为1表示该引脚为通用输出引脚,否则该引脚功能由引脚配置寄存器决定(默认) 161 */ 162 #define CNTL_ADDR_GPIO_W_CONF (8 << 11) //GPIO写配置,选择哪些引脚是GPIO输出 163 #define GPIO_W_CONF_IO7_BUSY (1 << 8) //#0:表示I/O7未配置为BUSY功能。#1:I/O7引脚配置为BUSY功能,D7也必须设置为1 164 165 /** 166 * \brief GPIO写数据寄存器,[D15:D8]固定为0100 1000,[D7:D0]确定引脚输出电平 167 */ 168 #define CNTL_ADDR_GPIO_W_DATA (9 << 11) //向GPIO写数据 169 170 171 /** 172 * \brief GPIO读配置寄存器,[D15:D11]固定为0101 0,[D9:D8]:固定为0。[D7:D0]某位为0则表示该引脚输入/输出功能由配置寄存器决定,为1表示这是一个通用的输入引脚 173 */ 174 #define CNTL_ADDR_GPIO_R_CONF (10 << 11) //GPIO读配置,选择哪些引脚是GPIO输入 175 #define GPIO_R_CONF_EN_RDBK (1 << 10) //#0:[D7:D0]确定哪些引脚为通用输入,#1:写一个SPI操作会计时(clocks)GPIO引脚的状态 176 177 /** 178 * \brief 断电/参考控制寄存器,[D15:D11]固定为0101 1,D8固定为0,[D7:D0]某位为0则表示通道处于正常工作模式(默认),为1时如果通道配置为DAC,则该通道断电 179 */ 180 #define CNTL_ADDR_POW_DOWN_REF_CNTL (11 << 11) //断电/参考控制,关闭DAC并启用/禁用参考 181 #define POW_DOWN_REF_CNTL_PD_ALL (1 << 10) //#0:参考和DAC断电状态由D9及[D7:D0]确定(默认)。#1:基准、DAC和ADC断电 182 #define POW_DOWN_REF_CNTL_EN_REF (1 << 9) //#0:参考和buffer断电,如果使用外部参考,则设置该位。#1:基准及buffer通电,参考源为VREF引脚 183 184 /** 185 * \brief GPIO开漏配置寄存器,[D15:D8]固定为0110 0000,[D7:D0]某位为1表示该引脚为开漏输出引脚,引脚也必须设置为数字输出引脚。为0则表示改引脚设置为上/下拉 186 */ 187 #define CNTL_ADDR_GPIO_OD_CONF (12 << 11) //GPIO开漏配置,为GPIO选择开漏或上/下拉 188 189 /** 190 * \brief 三态配置寄存器,[D15:D8]固定为0110 1000,[D7:D0]:#0:输入/输出功能由引脚配置寄存器决定。#1:该引脚为三态输出 191 */ 192 #define CNTL_ADDR_GPIO_3_STAT_CONF (13 << 11) //三态配置,选择哪些引脚是三态 193 #define CNTL_ADDR_RESERV (14 << 11) //保留 194 195 /** 196 * \brief 软件复位写入序列:0111 1101 1010 1100,即0x7DAC 197 */ 198 #define CNTL_ADDR_SOFT_REST (15 << 11) //软件复位 199 /** 200 * @} 201 */ 202 203 /** 204 * @} 205 */ 206 207 208 /** 209 * \brief IO引脚配置寄存器 210 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 211 * |D15|D14|D13|D12|D11|D10|D9 |D8 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | 212 * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 213 * | 0 | 寄存器地址 | 保留 |IO7|IO6|IO5|IO4|IO3|IO2|IO1|IO0| 214 * +---+---------------+-----------+---+---+---+---+---+---+---+---+ 215 * @{ 216 */ 217 218 /** 219 * \brief IO引脚配置寄存器地址,[D14:D11]选择功能,[D7:D0]选择是否使能该功能 220 * @{ 221 */ 222 #define IO_CONF_ADDR_ADC_PIN (4 << 11) //配置为ADC引脚 223 #define IO_CONF_ADDR_DAC_PIN (5 << 11) //配置为DAC引脚 224 #define IO_CONF_ADDR_PULL_DOWN (6 << 11) //配置为下拉(默认配置为上拉) 225 #define IO_CONF_ADDR_GPIO_W_CONF (8 << 11) //配置为GPIO写 226 #define IO_CONF_ADDR_GPIO_R_CONF (10 << 11) //配置为GPIO读 227 #define IO_CONF_ADDR_GPIO_OD_CONF (12 << 11) //配置为GPIO开漏 228 #define IO_CONF_ADDR_3_STAT_CONF (13 << 11) //配置为三态 229 /** 230 * @} 231 */ 232 233 /** 234 * @} 235 */ 236 237 /** 238 * \brief 通用控置寄存器,[D15:D10] 固定为0 0011 0,[D3:D0]固定为0000 239 * @{ 240 */ 241 #define GP_COTL_ADC_BUF_PRECHARGE (1 << 9) //#0:ADC缓冲器不用于对ADC预充电,如果ADC缓冲区已经启用,则始终通电(默认) 242 //#1:ADC缓冲器用于对ADC预充电,如果ADC缓冲区已经启用,则在转换发生时将其通电,然后断电,直到下一次转换发生 243 #define GP_COTL_ADC_BUF_EN (1 << 8) //#0:ADC缓冲器禁能(默认),#1:ADC缓冲器使能 244 #define GP_COTL_LOCK (1 << 7) //#0:可以更改输入/输出引脚配置寄存器的内容(默认),#1:不能更改…… 245 #define GP_COTL_ALL_DAC (1 << 6) //#0:对于未来的DAC写入,DAC地址位确定写入哪个DAC(默认) 246 //#1:对于未来的DAC写入,DAC地址位将被忽略,配置为DAC的所有通道将使用相同的数据进行更新 247 #define GP_COTL_ADC_RANGE_REFx2 (1 << 5) //#0:ADC增益为0~Vref(默认)。#1:ADC增益为0~2Vref 248 #define GP_COTL_DAC_RANGE_REFx2 (1 << 4) //#0:ADC增益为0~Vref(默认)。#1:DAC增益为0~2Vref 249 /** 250 * @} 251 */ 252 253 254 /** 255 * \brief 函数声明 256 * @{ 257 */ 258 /** 259 * /brief 初始化AD5592R 260 */ 261 extern void AD5592R_Init(void); 262 263 /** 264 * \brief AD5592R硬件复位 265 */ 266 extern void AD5592R_HW_Reset(void); 267 268 /** 269 * \brief 读取AD5592R的寄存器 270 * 271 * \param[in] addr:寄存器地址 272 * 273 * \note D1和D0用来选择LDAC模式,每当调用一次该函数时,都会将模式设定为DAC即时更 274 * 新模式,需要修改的话,可以用一个变量保存。 275 */ 276 extern u16 AD5592R_Read_Register(ad5592r_addr_t addr); 277 278 /** 279 * \brief 读取AD5592R的寄存器 280 * 281 * \note 这个函数主要是用来测试,读出来15个寄存器的值。芯片复位后读取,其中data[6]为0x00FF,data[7]为0x005C,其他寄存器的值都为0,如果读出的结果都为0xFFFF,那可能通信出现问题了 282 */ 283 extern void AD5592R_Read_All_Register(u16 data[16]); 284 285 /** 286 * \brief 通用控制寄存器配置 287 * 288 * \param[in] flag:可以加入如下标志: 289 * #GP_COTL_ADC_BUF_PRECHARGE: ADC缓冲器用于对ADC预充电,不设置则禁用(默认) 290 * #GP_COTL_ADC_BUF_EN: 使能ADC缓冲器,不设置则禁能(默认) 291 * #GP_COTL_LOCK: 不能改变I/Ox引脚配置寄存器的内容,不设置则可以改变(默认) 292 * #GP_COTL_ALL_DAC: (一个数据)写入所有DAC,不设置则由DAC地址决定写入哪个DAC(默认) 293 * #GP_COTL_ADC_RANGE_REFx2: ADC增益为0 V至2 × VREF,不设置则为1倍(默认) 294 * #GP_COTL_DAC_RANGE_REFx2: DAC增益为0 V至2 × VREF,不设置则为1倍(默认) 295 */ 296 extern void AD5592R_GP_Contol_Set(u16 flag); 297 298 299 /** 300 * \brief 将指定的引脚配置为指定的功能 301 * 302 * \param[in] func:设定的功能#ADC_PIN_CONF:配置为ADC引脚 303 * #DAC_PIN_CONF:配置为DAC引脚 304 * #PD_CONF:下拉配置,设定为85kΩ下拉(默认就是这个) 305 * #GPIO_W_CONF:GPIO写配置,意思就是将引脚配置为GPIO输出 306 * #GPIO_R_CONF:GPIO读配置,意思就是将引脚配置为GPIO输入 307 * #GPIO_OD_CONF:GPIO开漏配置,意思就是将引脚配置为开漏输出,否则为推挽输出(默认) 308 * #GPIO_3_STAT_CONF:三态配置 309 * \param[in] pin:选择需要配置的引脚,取值为AD5592R_PIN_0~AD5592R_PIN_7,可以按 310 * 位或。 311 * 312 * 313 * \param[in] flag:根据func的值,可以传入一些特殊标志,具体如下: 314 * 1、如果写入的func值为 GPIO_W_CONF,则传入的flag可以加入 315 * AD5592R_PIN_7_BUSY,表示将PIN7设定为BUSY引脚。 316 * 2、如果写入的func值为GPIO_R_CONF,则传入的flag可以加入 317 * GPIO_R_CONF_EN_RDBK,表示下一个SPI操作输出GPIO引脚的状态, 318 * 并将状态通过返回值返回。 319 * 320 * 321 */ 322 extern u8 AD5592R_Pin_Config(ad5592r_addr_t func, u8 pin, u16 flag); 323 324 /** 325 * \brief 给8个GPIO写入数据 326 * 327 * \param[in] value:要写入的值 328 */ 329 extern void AD5592R_GPIO_Write(u8 value); 330 331 /** 332 * \brief 给DAC通道写入数据 333 * 334 * \param[in] channel:0~7有效,指定DAC通道 335 * \param[in] value:要写入的值,低12位有效 336 */ 337 extern void AD5592R_DAC_Write_Data(u8 channel, u16 value); 338 339 /** 340 * \brief 配置DAC通道回读 341 * 342 * \param[in] channel:0~7有效,指定DAC通道 343 * \param[in] value:要写入的值,低12位有效 344 * 345 * \todo 指的是当某个DAC通道使能以后,每次写DAC数据后的下一个时钟周期读出数据? 346 * 还是说每次使能回读之后的下一个时钟周期读出数据?本函数写的是后者。 347 */ 348 extern u16 AD5592R_DAC_Readback(u8 channel); 349 350 /** 351 * \brief 设定关断DAC和内部基准电压源 352 * 353 * \param[in] value:#true:关断基准电压源、 DAC和ADC 354 * #false:基准电压源和DAC关断状态由D9和D7至D0决定(默认)。 355 */ 356 extern void AD5592R_PD_ALL_Set(u8 value); 357 358 /** 359 * \brief 选择基准电压源 360 * 361 * \param[in] value: #REF_INTERNAL:使用内部基准电压源 362 * #REF_EXTERNAL:使用外部基准电压源 363 */ 364 extern void AD5592R_Ref_Set(ref_select_t value); 365 366 /** 367 * \brief 选择关断DAC 368 * 369 * \param[in] pin:选择需要配置的引脚,取值为AD5592R_PIN_0~AD5592R_PIN_7,可以按 370 * 位或。 371 * \param[in] mode: #MORMAL_MODE:选择的引脚设置为正常模式 372 * #PD_MODE:引脚若配置为DAC则关断 373 */ 374 extern void AD5592R_PD_DAC(u8 pin, pd_mode_t mode); 375 376 /** 377 * \brief ADC序列寄存器设置 378 * 379 * \prarm[in] channel:0~7有效,指定需要加入转换序列的ADC通道 380 * \prarm[in] flag:可以加入如下标志: 381 * #ADC_SEQ_REP:使能序列重复,不设置则禁用序列重复(默认) 382 * #ADC_SEQ_TEMP:使能温度指示器回读,不设置则禁用温度指示器回读(默认) 383 */ 384 extern void AD5592R_ADC_Sequence_set(u8 channel, u16 flag); 385 386 387 /** 388 * \brief AD5592R软件复位 389 */ 390 extern void AD5592R_Soft_Reset(void); 391 392 /** 393 * @} 394 */ 395 396 #endif
标签:GPIOB,Pin,代码,STM32,SPI,InitStructure,AD5592R,GPIO 来源: https://www.cnblogs.com/Suzkfly/p/16475202.html