今天使用DAC751实现输出0-5V电压,效果良好精度很高。
DAC7512时序图。需要注意的是要给出5V参考电压,实现DAC5V正常输出。根据时序图,在开启写入数据之前,片选信号拉高再拉低,然后时钟线和数据线同步写入16个数据,之后片选信号线拉高,完成16位数据写入。
软件代码
引脚配置
初始化引脚配置为3个推挽输出即可。
#define SOFT_CLK_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET)
#define SOFT_CLK_0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET)
#define SOFT_Data_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET)
#define SOFT_Data_0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET)
#define SOFT_CS_1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
#define SOFT_CS_0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
1us延时函数实现
static u32 fac_us=0;
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us; //需要的节拍数
delay_osschedlock(); //阻止OS调度,防止打断us延时
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
};
delay_osschedunlock(); //恢复OS调度
}
软件模式SPI实现过程
void dac7512_SendData(uint16_t data)
{
#ifdef SOFT_SPI /* 软件SPI */
int i;
SOFT_CS_1;
SOFT_CLK_1;
SOFT_Data_1;
delay_us(1);
SOFT_CS_0;
delay_us(1);
for (i = 0; i < 16; ++i) {
if (0x8000&data) {
//判断写入0还是写入1
SOFT_Data_1; //写入1
}
else {
SOFT_Data_0; //写入0
}
delay_us(1);
SOFT_CLK_0;
data = data << 1;
delay_us(1);
SOFT_CLK_1;
}
SOFT_CS_1;
SOFT_CLK_1;
SOFT_Data_1;
#endif
#ifdef HARD_SPI /* 硬件SPI */
SOFT_CS_0;
while(__HAL_SPI_GET_FLAG(&hspi1,SPI_FLAG_TXE) == RESET)
HAL_SPI_Transmit(hspi1, data, 1, 1000);
SOFT_CS_1;
#endif
}
1us延时函数实现
主函数实现
输出一个锯齿波。
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(336,8,2,7); //设置时钟,168Mhz
delay_init(168); //初始化延时函数
LED_Init(); //初始化LED
int i;
while(1)
{
for(i = 0;i <4095;i++)
dac7512_SendData(i);
for(i = 4095;i >0;i--)
dac7512_SendData(i);
}
}
实验现象
锯齿波输出,示波器查看波形。