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);
}
}