STM32硬件SPI驱动DAC8760

1、SPI配置

2、driver_spi_dac8760.h

#ifndef _DRIVER_SPI_DAC8760_H
#define _DRIVER_SPI_DAC8760_H

#include "stm32f4xx_hal.h"
#include "gpio.h"
#include "spi.h"


#define HSPI_DAC8760			hspi1

#define DAC8760_CS_GPIO_PORT	GPIOA
#define DAC8760_CS_GPIO_PIN   	GPIO_PIN_4
#define DAC8760_TIMEOUT       	500


/** DAC8760 ****/
#define  V_0_P5					0x0000		//电压范围0~+5V
#define  V_0_P10				0x0001		//电压范围0~+10V
#define  V_N5_P5				0x0002		//电压范围-5~+5V
#define  V_N10_P10				0x0003		//电压范围-10~+10V

/* DAC8760 写操作 */
#define W_ADDR_NOP				0x00
#define W_ADDR_DATA				0x01		// 写数据寄存器
#define W_ADDR_READ				0x02		// 读寄存器
#define W_ADDR_CTRL				0x55		// 写控制寄存器
#define W_ADDR_RESET			0x56		// 写复位寄存器
#define W_ADDR_CONFIG			0x57		// 写配置寄存器
#define W_ADDR_GAIN				0x58		// 写增益校准寄存器
#define W_ADDR_ZERO				0x59		// 写零校准寄存器
#define W_ADDR_WDTRST			0x95		// 看门狗时间复位
#define W_ADDR_CRCERRRST		0x96		// CRC错误复位

/* DAC8760 读操作寄存器地址 */ 
#define R_ADDR_SATUS			0x00
#define R_ADDR_DATA				0x01
#define R_ADDR_CTRL				0x02
#define R_ADDR_CONFIG			0x0B
#define R_ADDR_GAIN				0x13
#define R_ADDR_ZERO				0x17



void lockDac8760Spi(void);
void unlockDac8760Spi(void);
void Dac8760Init(void);
int Dac8760Write(uint8_t addr, uint16_t data);
int Dac8760Read(uint8_t addr_r, uint16_t *data);
void Dac8760Test(void);

#endif /* _DRIVER_SPI_DAC8760_H */

3、driver_spi_dac8760.c

/**
  ******************************************************************************
  * @file    driver_spi_dac8760.c
  * @author  GLC
  * @version V1.0
  * @date    2024-05-27
  * @brief   dac8760驱动程序。 
  ******************************************************************************
  * @attention 
  * 
  * 修改历史     版本号           作者        修改内容
  *-----------------------------------------------------
  * 2024.05.27    v1.0             GLC        创建文件
  *-----------------------------------------------------
  */

#include "driver_spi_dac8760.h"
#include "driver_timer.h"
#include "driver_debug_usart.h"
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"


static SemaphoreHandle_t	g_xMutexDac8760Spi;

/**
  * @brief Dac8760Select 
  * @param None
  * @retval None
  * @attention 
  * 
  */ 
static void Dac8760Select(void)
{
    HAL_GPIO_WritePin(DAC8760_CS_GPIO_PORT, DAC8760_CS_GPIO_PIN, GPIO_PIN_RESET);
}

/**
  * @brief Dac8760Deselect 
  * @param None
  * @retval None
  * @attention 
  * 
  */ 
static void Dac8760Deselect(void)
{
    HAL_GPIO_WritePin(DAC8760_CS_GPIO_PORT, DAC8760_CS_GPIO_PIN, GPIO_PIN_SET);
}

/**
  * @brief Dac8760TxRx  使用SPI发送/接收数据 
  * @param pTxData - 要发送的数据
  * 		Size    - 数据长度
  *			Timeout - 超时时间(单位ms)
  *			pRxData - 接收缓冲区
  * @retval 0 - 成功, (-1)-失败
  * @attention 
  * (注意这个函数没有设置片选信号)
  */ 
static int Dac8760TxRx(uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
    if (HAL_OK == HAL_SPI_TransmitReceive(&HSPI_DAC8760, pTxData, pRxData, Size, Timeout))
        return 0;
    else
        return -1;
}

/**
  * @brief Dac8760Tx  使用SPI发送数据 
  * @param pTxData - 要发送的数据
  * 		Size    - 数据长度
  *			Timeout - 超时时间(单位ms)
  * @retval 0 - 成功, (-1)-失败
  * @attention 
  * (注意这个函数没有设置片选信号)
  */ 
static int Dac8760Tx(uint8_t *pTxData, uint16_t Size, uint32_t Timeout)
{
    if (HAL_OK == HAL_SPI_Transmit(&HSPI_DAC8760, pTxData, Size, Timeout))
        return 0;
    else
        return -1;
}

/**
  * @brief Dac8760Rx  使用SPI读取数据 
  * @param pRxData - 接收缓冲区
  * 		Size    - 数据长度
  *			Timeout - 超时时间(单位ms)
  * @retval 0 - 成功, (-1)-失败
  * @attention 
  * (注意这个函数没有设置片选信号)
  */ 
static int Dac8760Rx(uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
    if (HAL_OK == HAL_SPI_Receive(&HSPI_DAC8760, pRxData, Size, Timeout))
        return 0;
    else
        return -1;
}

/**
  * @brief lockDac8760Spi 
  * @param None
  * @retval None
  * @attention 
  * 
  */ 
void lockDac8760Spi(void)
{
	xSemaphoreTake(g_xMutexDac8760Spi, portMAX_DELAY);
}

/**
  * @brief unlockDac8760Spi 
  * @param None
  * @retval None
  * @attention 
  * 
  */ 
void unlockDac8760Spi(void)
{
	xSemaphoreGive(g_xMutexDac8760Spi);
}

/**
  * @brief Dac8760Init Dac8760的初始化函数
  * @param None
  * @retval None
  * @attention 
  * 
  */
void Dac8760Init(void)
{
    /* 1 片选信号引脚配置,已在gpio.c中被配置为输出引脚 */
	
    /* 2 SPI配置,SPI已在spi.c中配置好 */
	
	/* 3 片选信号引脚释放 */
	Dac8760Deselect();
	
	/* 4 创建互斥量 */
	g_xMutexDac8760Spi = xSemaphoreCreateMutex();
}

/**
  * @brief Dac8760Write  写函数
  * @param addr - 写哪个地址, 写操作
  * 		data    - 写数据
  * @retval 0 - 成功, 非0 - 失败
  * @attention 
  * 
  */ 
int Dac8760Write(uint8_t addr, uint16_t data)
{
	uint8_t tmpbuf[3];
    int ret;
    
    /* 自己实现SPI的写操作 */
    tmpbuf[0] = addr;
    tmpbuf[1] = (data >> 8) & 0xff;
    tmpbuf[2] = (data >> 0) & 0xff;
    
    Dac8760Select();

    /* 发送写命令 */
    ret = Dac8760Tx(tmpbuf, 3, DAC8760_TIMEOUT);

    Dac8760Deselect();    
	
    return ret;
}

/**
  * @brief Dac8760Read 读函数
  * @param addr_r - 读哪个地址
  *			data - 用来保存读到的数据
  * @retval 0 - 成功, 非0 - 失败
  * @attention 
  * 
  */ 
int Dac8760Read(uint8_t addr_r, uint16_t *data)
{
	uint8_t tmpbuf[3], rcvbuf[3];
    int ret;
	
	tmpbuf[0] = W_ADDR_READ;
    tmpbuf[1] = 0x00;
    tmpbuf[2] = addr_r;
	
	Dac8760Select();

    /* 发送写命令 */
    ret = Dac8760Tx(tmpbuf, 3, DAC8760_TIMEOUT);
	
	if (ret)
	{
		Dac8760Deselect();
		return ret;
	}
	
	Dac8760Deselect();
	udelay(1);
	Dac8760Select();
	ret = Dac8760Rx(rcvbuf, 3, DAC8760_TIMEOUT);
	Dac8760Deselect();
	*data = rcvbuf[1];
	*data <<= 8;
	*data |= rcvbuf[2];
	
	return ret;
}


/**
  * @brief Dac8760Test 测试程序
  * @param None
  * @retval None
  * @attention 
  * 
  */
void Dac8760Test(void)
{
	int ret;
	uint16_t temp;
	Dac8760Init();
	
	Dac8760Write(W_ADDR_RESET,0x0001);						// 0x56 复位寄存器   0x0001执行软件复位
	// 0x55 控制寄存器  (1<<12)|V_N10_P10设置电压输出模式-10~+10V,并且使能控制寄存器第12位
	// bit15为0,复位输出0V
    Dac8760Write(W_ADDR_CTRL,(1<<12)|V_N10_P10);			
    Dac8760Write(W_ADDR_CONFIG,0x0000);						// 0x57 配置寄存器   0x0000设置单电压模式,电流输出0 
	
	ret = Dac8760Read(R_ADDR_CTRL, &temp);
	printf("ret = %d\t temp = %d\n", ret, temp);
	
	mdelay(5000);
		
    while (1)
    {
		ret = Dac8760Write(W_ADDR_DATA,0);
		printf("ret = %d\t value = 0\n", ret);
		mdelay(5000);
		ret = Dac8760Write(W_ADDR_DATA,32768);
		printf("ret = %d\t value = 32758\n", ret);
		mdelay(5000);
		ret = Dac8760Write(W_ADDR_DATA,65535);
		printf("ret = %d\t value = 65535\n", ret);
		mdelay(5000);
    }
}


234 • 输 出 电 流 :4mA 至 至 20mA ; DAC7760 和 DAC8760 是低成本,高精度,全面集 0mA 至 至 20mA ;0mA 至 至 24mA 成,12 位和 16 位数模转换器 (DAC),此转换器设计 • 电 压 输 出 : 用于满足工业过程控制应用的需要。 这些器件可被设 – 0V 至 至 5V ;0V 至 至 10V ;±5V ;±10V 定为一个范围介于 4mA 至 20mA,0mA 至 20mA,或 – 0V 至 至 5.5V ;0V 至 至 11V ;±5.5V ;±11V 0mA 至 24mA 的电流输出;或者作为一个范围介于 ( 超 出 量 程 范围 围 10% ) 0V 至 5V,0V 至 10V,±5V,或 ±10V 的电压输出, • ±0.1% 满 量 程 范围 围 (FSR) 总 不 可 调 整 误差 差 (TUE) 可超出量程范围 10%(0V 至 5.5V,0V 至 最 大 值 11V,±5.5V,或 ±11V)。 电流和电压输出在由一个 • 微 分 非 线性 性 (DNL) :±1 最 低 有 效位 位 (LSB) 最 大 值 单个数据寄存器进行控制的同时,可被同时启用。 • 同 步 电 压 和 电 流 输 出 这些器件包括一个加电复位功能,以确保在一个已知状 • 内部 部 5V 基 准 (10 ppm/°C , 最 大 值 ) 态中加电(IOUT 和 VOUT 被禁用,并且处于高阻抗 • 内部 部 4.6V 电 源 输 出 (Hi-Z) 状态)。 CLR 和 CLR-SEL 引脚将电压输出设 • 可 靠 特 性 : 定为零量程或中量程,并且在输出被启用时,电流输出 – 循 环 冗 余码 码 (CRC) 校 验 和 看 门 狗 定 时 器 被设定为量程范围的低端。 零和增益寄存器可被设定 – 过 热 警 报 为在终端系统中对器件进行数字校准。 输出转换率也 – 开 路 警 报 , 短 接 电 流 限 制 由寄存器设定。 这些器件可在电流输出上添加一个外 • 宽 温 度 范 围 :-40°C 至 至 +125°C 部 HART ® 信号,并且可由一个 +10V 至 +36V 单电 • 6mm × 6mm 四 方 扁 平 无 引线 线 (QFN)-40 ; 薄 型 小 源,或高达 ±18V 的双电源供电运行。全部器件版本采 外 形 尺寸 寸 (TSSOP)-24 封 装 用 6mm × 6mm QFN-40 和 TSSOP-24 封装。
### DAC8760 SPI 驱动开发文档与代码示例 对于DAC8760器件而言,其SPI接口通信协议的具体实现依赖于所使用的微控制器平台以及相应的库支持。通常情况下,制造商Texas Instruments会提供详细的Datasheet和技术手册来指导开发者如何配置和操作该设备。 #### 使用STM32 HAL 库进行DAC8760 SPI驱动开发 当采用STM32系列单片机作为主控器时,可以利用官方提供的HAL库简化外设控制逻辑的设计工作。虽然上述提到的内容主要针对STM32F4系列芯片及其配套资源[^1],但是这些工具同样适用于其他型号的STM32产品线,在编写DAC8760相关的SPI驱动程序时可借鉴如下方法: - **初始化SPI模块**:通过调用`MX_SPIx_Init()`函数完成硬件层面上的设置; ```c void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } ``` - **发送数据至DAC8760**:构建命令帧并借助`HAL_SPI_Transmit()` API向目标寄存器写入数值; ```c uint8_t spi_tx_buffer[] = {COMMAND_BYTE, DATA_HIGH_BYTE, DATA_LOW_BYTE}; if(HAL_SPI_Transmit(&hspi1, spi_tx_buffer, sizeof(spi_tx_buffer), HAL_MAX_DELAY)!= HAL_OK){ /* Transfer error in transmission process */ Error_Handler(); } ``` 需要注意的是,具体的参数定义(如`COMMAND_BYTE`, `DATA_HIGH_BYTE`, 和 `DATA_LOW_BYTE`)应当依据DAC8760的数据表中的描述来进行调整。 另外,如果考虑使用Atmel公司的AVR或其他MCU,则可以从特定厂商网站获取更多关于SPI编程的帮助和支持材料[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值