糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 基于STM32的数模转换芯片AD5328驱动程序

基于STM32的数模转换芯片AD5328驱动程序

时间:2021-04-24 14:47:06

相关推荐

基于STM32的数模转换芯片AD5328驱动程序

一个项目中需要输出4路0~5V模拟量,主控芯片为STM32F103单片机,选用了AD5328作为DAC输出;

AD5328是ADI的一款DAC芯片,可输出8路模拟量,SPI通讯,自己根据AD5328数据手册,基于STM32编写了AD5328驱动程序,并且经过项目测试,使用无问题,可单独对通道进行开关,可单独设置各通道输出电压值。

(注:我在项目中设计的AD5328的参考电压为2.5V,另外在输出口设计下拉电阻(我设计的100k下拉),这样关闭通道时可下拉至0V)

驱动程序如下,使用HAL库编程(删除了其他无关程序,仅保留AD5328驱动程序,并添加了详细注释):

头文件bsp_spi_ad5328.h

#ifndef __BSP_SPI_AD5328_H#define __BSP_SPI_AD5328_H#include "stm32f1xx.h"#include <stdio.h>/* Private typedef -----------------------------------------------------------*//*时钟使能宏定义*/#define SPIxSPI1#define SPIx_CLK_ENABLE()__HAL_RCC_SPI1_CLK_ENABLE()#define SPIx_SCK_GPIO_CLK_ENABLE()__HAL_RCC_GPIOA_CLK_ENABLE()#define SPIx_MISO_GPIO_CLK_ENABLE()__HAL_RCC_GPIOA_CLK_ENABLE() #define SPIx_MOSI_GPIO_CLK_ENABLE()__HAL_RCC_GPIOA_CLK_ENABLE() #define SPIx_CS_GPIO_CLK_ENABLE()__HAL_RCC_GPIOA_CLK_ENABLE() #define LDAC_GPIO_CLK_ENABLE()__HAL_RCC_GPIOB_CLK_ENABLE()#define SPIx_FORCE_RESET()__HAL_RCC_SPI1_FORCE_RESET()#define SPIx_RELEASE_RESET()__HAL_RCC_SPI1_RELEASE_RESET()/* Definition for SPIx Pins */#define SPIx_SCK_PINGPIO_PIN_5#define SPIx_SCK_GPIO_PORTGPIOA#define SPIx_MISO_PINGPIO_PIN_6#define SPIx_MISO_GPIO_PORTGPIOA#define SPIx_MOSI_PINGPIO_PIN_7#define SPIx_MOSI_GPIO_PORTGPIOA#define AD5328_CS_PINGPIO_PIN_4 #define AD5328_CS_GPIO_PORTGPIOA //AD5328的LDAC引脚#define AD5328_LDAC_PINGPIO_PIN_0 #define AD5328_LDAC_GPIO_PORTGPIOB#definedigitalHi(p,i){p->BSRR=i;} //设置为高电平#define digitalLo(p,i){p->BSRR=(uint32_t)i << 16;}//输出低电平#define SPI_AD5328_CS_LOW()digitalLo(AD5328_CS_GPIO_PORT,AD5328_CS_PIN )#define SPI_AD5328_CS_HIGH()digitalHi(AD5328_CS_GPIO_PORT,AD5328_CS_PIN )#define AD5328_LDAC_LOW()digitalLo(AD5328_LDAC_GPIO_PORT,AD5328_LDAC_PIN )#define AD5328_LDAC_HIGH()digitalHi(AD5328_LDAC_GPIO_PORT,AD5328_LDAC_PIN )/*SPI接口定义-结尾****************************//*等待超时时间*/#define SPIT_FLAG_TIMEOUT((uint32_t)0x1000)#define SPIT_LONG_TIMEOUT((uint32_t)(10 * SPIT_FLAG_TIMEOUT))extern uint16_t PDCtrl;//PowerDown指令全局变量void SPI_AD5328_Init(void);uint16_t SPI_AD5328_SendHalfWord(uint16_t HalfWord);void AD5328_Init(void);void AD5328_PowerDown(uint8_t Channel);void AD5328_PowerUp(uint8_t Channel);void AD5328_ValueSet(uint8_t Channel,uint16_t Val);#endif /* __BSP_SPI_AD5328_H */

源程序文件bsp_spi_ad5328.c

包含头文件及变量定义:

#include "bsp_spi_ad5328.h"SPI_HandleTypeDef SpiHandle;static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT; static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);uint16_t PDCtrl = 0xc0ff;//power down 命令

SPI的MSP底层外设初始化程序:

/*** @brief SPI MSP Initialization * This function configures the hardware resources used in this example: * - Peripheral's clock enable* - Peripheral's GPIO Configuration * @param hspi: SPI handle pointer* @retval None*/void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi){GPIO_InitTypeDef GPIO_InitStruct;/*##-1- Enable peripherals and GPIO Clocks #################################*//* Enable GPIO TX/RX clock */SPIx_SCK_GPIO_CLK_ENABLE();SPIx_MISO_GPIO_CLK_ENABLE();SPIx_MOSI_GPIO_CLK_ENABLE();SPIx_CS_GPIO_CLK_ENABLE();/* Enable SPI clock */SPIx_CLK_ENABLE(); /*AD5328的LDAC引脚*/LDAC_GPIO_CLK_ENABLE();/*##-2- Configure peripheral GPIO ##########################################*/ /* SPI SCK GPIO pin configuration */GPIO_InitStruct.Pin = SPIx_SCK_PIN;GPIO_InitStruct.Mode= GPIO_MODE_AF_PP;GPIO_InitStruct.Pull= GPIO_PULLUP;GPIO_InitStruct.Speed= GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);/* SPI MISO GPIO pin configuration */GPIO_InitStruct.Pin = SPIx_MISO_PIN; HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct);/* SPI MOSI GPIO pin configuration */GPIO_InitStruct.Pin = SPIx_MOSI_PIN; HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct); //CSGPIO_InitStruct.Pin = AD5328_CS_PIN ;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;HAL_GPIO_Init(AD5328_CS_GPIO_PORT, &GPIO_InitStruct); //LDACGPIO_InitStruct.Pin = AD5328_LDAC_PIN ;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;HAL_GPIO_Init(AD5328_LDAC_GPIO_PORT, &GPIO_InitStruct);}

用于与AD5328通讯的SPI外设初始化:

/*** @brief SPI Peripheral Initialization * This function configures the SPI peripheral * @param None* @retval None*/void SPI_AD5328_Init(void){/*##-1- Configure the SPI peripheral #######################################*//* Set the SPI parameters */SpiHandle.Instance= SPIx;//指向SPIx基地址SpiHandle.Init.BaudRatePrescaler= SPI_BAUDRATEPRESCALER_4;//SPI1挂在APB2总线,时钟72M/4=18MHzSpiHandle.Init.Direction= SPI_DIRECTION_1LINE;//单线双向传输,后面有指令设置发送或接收SpiHandle.Init.CLKPhase= SPI_PHASE_2EDGE;//偶数边沿采样SpiHandle.Init.CLKPolarity= SPI_POLARITY_LOW;//时钟空闲状态为低电平,偶数边沿采样,即下降沿采样SpiHandle.Init.CRCCalculation= SPI_CRCCALCULATION_DISABLE;//不使用CRC校验SpiHandle.Init.CRCPolynomial= 7;//CRC多项式,不使用,默认复位值为7SpiHandle.Init.DataSize= SPI_DATASIZE_16BIT;//传输数据宽度为16bit,AD5328控制指令为16bitSpiHandle.Init.FirstBit= SPI_FIRSTBIT_MSB;//AD5328控制指令从高位开始传输SpiHandle.Init.NSS= SPI_NSS_SOFT;//NSS即CS使用软件SpiHandle.Init.TIMode= SPI_TIMODE_DISABLE;//不使用TI模式SpiHandle.Init.Mode = SPI_MODE_MASTER;//主模式HAL_SPI_Init(&SpiHandle); SPI_1LINE_TX(&SpiHandle);//设置为单线发送__HAL_SPI_ENABLE(&SpiHandle);}

SPI发送半字:

有用到SPI错误回调,用不到的可删除。

/******************************************************************************** @brief SPI_AD5328_SendHalfWord.* @param HalfWord: Half Word to send.* @retval 错误代码处理回调函数*******************************************************************************/uint16_t SPI_AD5328_SendHalfWord(uint16_t HalfWord){SPITimeout = SPIT_FLAG_TIMEOUT;/* Loop while DR register in not emplty */while (__HAL_SPI_GET_FLAG( &SpiHandle, SPI_FLAG_TXE ) == RESET){if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(2);}/* Send Half Word through the SPIx peripheral */HAL_SPI_Transmit(&SpiHandle, (uint8_t *)&HalfWord, 1, 1000);//WRITE_REG(SpiHandle.Instance->DR, HalfWord);//直接将HalfWord写入DR寄存器,数据宽度SPI配置时需配置好return 0;}

AD5328的初始化:

/*** @brief AD5328 Initialization * This function configures the AD5328 * @param None* @retval None*/void AD5328_Init(void){/*初始化AD5328*//*片选使能通讯*/SPI_AD5328_CS_LOW();/*发送指令,设置增益/Vref缓冲的指令,0x803c设置为2倍增益和有缓冲*/SPI_AD5328_SendHalfWord(0x803c);/*通讯停止*/SPI_AD5328_CS_HIGH();/*关闭所有通道*//*片选使能通讯*/SPI_AD5328_CS_LOW();/*发送指令,关闭所有通道,0xc0ff关闭八个通道*/SPI_AD5328_SendHalfWord(PDCtrl);/*通讯停止*/SPI_AD5328_CS_HIGH();/*LDAC拉低,DAC寄存器连续更新*/AD5328_LDAC_LOW();}

关闭AD5328的指定通道:

/*** @brief AD5328_PowerDown * @param Channel:通道1..8* @retval None*/void AD5328_PowerDown(uint8_t Channel){PDCtrl |= (0x0001<<(Channel-1));//操作对应通道的命令位/*片选使能通讯*/SPI_AD5328_CS_LOW();/*发送指令,PowerDown对应通道*/SPI_AD5328_SendHalfWord(PDCtrl);/*通讯停止*/SPI_AD5328_CS_HIGH();}

打开AD5328的指定通道:

/*** @brief AD5328_PowerUp * @param Channel:通道1..8* @retval None*/void AD5328_PowerUp(uint8_t Channel){PDCtrl &= (~(0x0001<<(Channel-1)));//操作对应通道的命令位/*片选使能通讯*/SPI_AD5328_CS_LOW();/*发送指令,PowerDown对应通道*/SPI_AD5328_SendHalfWord(PDCtrl);/*通讯停止*/SPI_AD5328_CS_HIGH();}

设置AD5328相应通道的值:

我这里定义的Val范围为0~100,是对应输出5V的0~100%,如想直接设置电压值可做相应更改。

/*** @brief AD5328_ValueSet * @param Channel:通道1..8* Val:DAC值,0..100* @retval None*/void AD5328_ValueSet(uint8_t Channel,uint16_t Val){uint16_t DAC_Val = Val*4095/100;/*片选使能通讯*/SPI_AD5328_CS_LOW();/*发送指令,PowerDown对应通道*/SPI_AD5328_SendHalfWord(((uint16_t)(Channel-1)<<12)+DAC_Val);/*通讯停止*/SPI_AD5328_CS_HIGH();}

SPI错误回调函数:

不需要的可删除。

/*** @brief 等待超时回调函数* @param None.* @retval None.*/static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode){/* 等待超时后的处理,输出错误信息 */FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);return 0;}

以上就是AD5328的基础驱动部分,使用时可其他应用程序中调用相应函数控制AD5328工作。

如果觉得《基于STM32的数模转换芯片AD5328驱动程序》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。