1、打开原理图,查看芯片对应的相应管脚

2、打开STM32CubeMX,添加相应管脚配置

3、输入的配置为无上下拉,输出该芯片对应的引脚配置和上图相同,一键生成代码,打开代码

4、新建“BspVout.c”和“BspVout.h”文件并添加在结构中,在“AppTask.h”文件中添加头文件“  #include "BspVout.h"   ”

5、在“BspVout.h”文件中添加代码

#define SPI_CS(x)  (HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, x))
#define SPI_CLK(x) (HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, x))
#define SPI_DIN(x) (HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, x))

作用是用宏定义控制输出信号,方便模拟SPI信号

6、分析数据手册

这是一张时序图,说明当CS信号为低电平的时候才能通讯,SCLK上升沿的那一瞬间读取DIN的电平信号

当CS是高电平时,SCLK为低电平,当CS由高电平转为低电平信号,SCLK的第一个上升沿读取的DIN电平信号为第一位数字信号,下图有说明

这里选择的是非菊花链式,所以按照Figuer 10 所示,数据信息与输出的关系见下图

这是一个十二位的锁存器,所以要十二的数字量,最后两位无效,但是必须加上

电压的输出关系是 Uout=2*Vrefin*输入的十二位(高十位有效)数值/1024,其中Vrefin是外部输入给芯片的参考电压,值为+2.5V,这个值要精准一些。

7、“BspVout.c”的代码如下

#include "BspVout.h"unsigned short Vount;void SPI_Vout(unsigned short Vout)
{unsigned short VData;VData = (unsigned short)(Vout * (1.024 / 2 / 2.5)+0.5);//由目标电压mV,计算十位数值SPI_CS(H);SPI_CLK(L);SPI_DIN(L);for(unsigned short i;i<3;i++);//>1ns  th(CSH0)SPI_CS(L);
//  for(unsigned char j=0;j<4;j++)//前四位
//  {
//      SPI_DIN(L);
//      for(unsigned short i;i<45;i++);//上升沿读取数值 >45ns  tsu(CSS)、tsu(DS)、tw(CL)
//      SPI_CLK(H);
//      for(unsigned short i;i<45;i++);//>25ns tw(CH)、th(DH)
//      SPI_CLK(L);
//  }for(unsigned char j=0;j<10;j++)//十位数据 ,j代表第几位(含0位){if(((VData >> (9-j)) & 0x01) == 0) //计算每一个位的电平{SPI_DIN(L);}else{SPI_DIN(H);}for(unsigned short i;i<5;i++);//上升沿读取位电平 >45ns  tsu(CSS)、tsu(DS)、tw(CL) SPI_CLK(H);for(unsigned short i;i<5;i++);//>25ns tw(CH)、th(DH)SPI_CLK(L);}for(unsigned char j=0;j<2;j++)//补充 后两位{SPI_DIN(L);for(unsigned short i;i<5;i++);//上升沿读取数值 >45ns  tsu(CSS)、tsu(DS)、tw(CL)SPI_CLK(H);for(unsigned short i;i<5;i++);//>25ns tw(CH)、th(DH)SPI_CLK(L);}SPI_DIN(L);for(unsigned short i;i<3;i++);//>0ns  th(CSH1)SPI_CS(H);for(unsigned short i;i<3;i++);//>20ns  tw(CS)
}void SYS_test1ms(void)
{SPI_Vout(Vount);}

8、“BspVout.h”的代码如下

#ifndef _BSPVOUT_H_
#define _BSPVOUT_H_#include "AppTask.h"#define SPI_CS(x)  (HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, x))
#define SPI_CLK(x) (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, x))
#define SPI_DIN(x) (HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, x))
#define H           GPIO_PIN_SET
#define L           GPIO_PIN_RESET  void SPI_Vout(unsigned short Vout);
void SYS_test1ms(void);#endif

9、“AppTask.c”的代码

#include "AppTask.h"extern unsigned short Vount;vinTime VRtime;//任务注册表
static TaskCtrl_t   TaskCtrl[] = //执行优先级程度 从上到下依次逐渐,第一个优先级最高,所有的任务函数都不能打断其它的任务函数
{/* 【实时任务】  【上电立即运行】    【初始counter】         【任务周期ms】                【任务指针】*/  //时间调度最好是cycle_task的整数倍{   1,                  0,              0,                      100/cycle_task,            taskTestTime},{ 0,                  0,              0/cycle_task,           500/cycle_task,             taskTest},{ 0,                  0,              0/cycle_task,           50/cycle_task,              SigLED},{   0,                  0,              0/cycle_task,           1/cycle_task,               SYS_test1ms},
};#define TASK_MAX_NUM  (sizeof(TaskCtrl)/sizeof(TaskCtrl[0])) //自动生成任务调度的数量给 TASK_MAX_NUMvoid App_task(void)
{volatile unsigned char i_task, j_task;static unsigned int timen_task;if(timen - timen_task >= cycle_task)//每间隔 cycle_task ms 执行一次{timen_task = timen;//和上面if括号的那句共同构成 每隔cycle_task个定时周期更新一次任务等待时长for(i_task = 0; i_task < TASK_MAX_NUM; i_task++)//把所有的任务检测一边{if((TaskCtrl[i_task].Task_Counter > 0) && (TaskCtrl[i_task].Task_RealTime == 0))//用于防止初始计数值为零,自减溢出TaskCtrl[i_task].Task_Counter--;if((TaskCtrl[i_task].Task_Counter == 0) && (TaskCtrl[i_task].Task_RealTime == 0))//自减为零的时候,认为该任务可以执行{TaskCtrl[i_task].Task_Running = true;//认为为可执行任务TaskCtrl[i_task].Task_Counter = TaskCtrl[i_task].Task_PeriodTime;//更新计时周期}}}for(j_task = 0; j_task < TASK_MAX_NUM; j_task++)//排队执行可执行函数{// 任务调用if(TaskCtrl[j_task].Task_Running || TaskCtrl[j_task].Task_RealTime){TaskCtrl[j_task].TaskHook();//执行函数TaskCtrl[j_task].Task_Running = false;//执行结束}}}sigLEDk sigLED;void AppInit(void)
{// 1-常亮; 2-T=200ms闪烁; 3-T=500ms闪烁; 4-T=1s闪烁; 0-常灭sigLED.LED01=1;sigLED.LED02=2;sigLED.LED03=3;sigLED.LED04=4;Vount = 1250; //用于Debug,用后删除
}void taskTest(void)
{static unsigned int time;for(unsigned char i=0;i<10;i++)TxBuff[i]=0x00+i;TxBuff[10]=0x0D;TxBuff[11]=0x0A;if((TxEndFlag == 0)&(timen - time >= 1000)){time = timen;PMJD_UART1_DMA_Send(TxBuff,12);}
}//实时性任务
void taskTestTime(void)
{unsigned char TxBuffTest[BUFFER_SIZE];if(RxEndFlag == 1)  //接收完成标志{for(unsigned char i=0;i<RxLen;i++){TxBuffTest[i]=RxBuff[i];}PMJD_UART1_DMA_Send(TxBuffTest, RxLen);//发送接收到的数据memset(RxBuff,0,RxLen);//清除接收到的数据RxLen = 0;//清除计数RxEndFlag = 0;//清除接收结束标志位}
}

10、编译下载程序,进入硬件在环仿真

11、在“Watch1”中添加变量 “Vount”,并改成十进制,运行仿真

实际拿万用表检测电压值,对应

改变数值,再检测

多改变几次

结果正常

STM32F103Cx用芯片tlc5615做DAC转换相关推荐

  1. tlc5615 c语言程序,第10章 TLC5615数模转换器DAC

    第10章 数模转换器DAC 1 D/A输出电路图 2 TLC5615基本测试实验 3 TLC5615产生波形实验 4 TLC5615播放音乐实验 数模转换就是将单片机输出的数字信号转换为模拟信号(比如 ...

  2. 一种高速ADC和DAC转换电路分享

    目录 1.高速ADC转换电路 2.高速DAC转换电路 ADC/DAC(Analog to Digital Converter/ Digital to Analog Converter,即模数转换器/数 ...

  3. 背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换...

    背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换 原文:背水一战 Windows 10 ...

  4. 在asp.net中做视频转换,将各种视频文件转换成.flv格式

    首先,我们部署一下文件夹.在工程的目录下新建几个文件夹如下图: UpFiles文件夹是要保存你上传的文件,PlayFiles文件夹是用于你转换后保存的文件(用于网上播放) ImgFile文件夹是保存截 ...

  5. ADC芯片CS1180的读取转换错误的情况记录

    ADC芯片CS1180的读取转换错误的情况记录 一.首先使用的是芯海的CS1180芯片 二.我的配置 三.最后找到原因 今天发现了一个情况,使用ADC芯片的时候一直读取不到正确的转换值,特此记录下来提 ...

  6. c语言adc0809小数点,ADC0809做AD转换的C程序

    ADC0809做AD转换的C程序 (2012-11-29 16:51:58) 标签: 杂谈 分类: 电学 #include unsigned char code dispbitcode[]={ 0x3 ...

  7. da0809 c语言程序,ADC0809做AD转换和DA转换的C程序.doc

    ADC0809做AD转换的C程序 #include unsigned char code dispbitcode[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x0 ...

  8. DCDC升压芯片可以做充电管理吗

    DCDC升压降压芯片可以做充电管理吗? 答案是:可以. 但因为不是专门的充电管理芯片,这时候的升压芯片没法直接实现充电管理芯片所具有的电量显示.

  9. 用limma对芯片数据做差异分析

    用limma对芯片数据做差异分析 用limma对芯片数据做差异分析 jmzeng 2016年3月12日 用基因芯片的手段来探针基因表达量的技术虽然已经在逐步被RNA-seq技术取代,但毕竟经历了十多年 ...

  10. Python标准库:codecs【专门做编码转换】【open()、encode()、decode()、lookup()、getencoder()】【读写文件codecs.open()优于open()】

    codecs专门用作编码转换,当我们要做编码转换的时候可以借助codecs很简单的进行编码转换 codecs模块提供一个open方法,三个参数encoding, errors, buffering,这 ...

最新文章

  1. KNN学习之图像分类与KNN原理
  2. 读者看《赢道:成功创业者的28条戒律》
  3. LoadRunner 8.1 学习笔记4
  4. iOS并发(多线程)
  5. python正则表达式初识(七)_Python正则表达式初识(二)
  6. Linux环境下设置IPDNSGateway
  7. python 垃圾回收详解
  8. 数据结构笔记(二十一)--二叉树的遍历
  9. Tomcat下WebSocket最大连接数测试
  10. oracle统计每个类别,Oracle统计分析函数集之一
  11. eplan p8详细安装步骤文库_Win10系统安装Eplan Electric P8详细步骤
  12. 【产品志】华硕 ARUA 的 ARGB 方案
  13. C#窗体-个人简历生成(自己设计并编写一个 Windows 应用程序,要求用到TextBox、GroupBox、RadioButton )
  14. CISCO路由基本配置命令
  15. 项目管理工具二、STAR原则
  16. TX-LCN分布式事务之LCN模式
  17. 如何将写好的网页放到服务器上,写好的网页怎么上传云服务器
  18. SwipeToLoadLayout布局中添加自定义控件仿美团、饿了吗等下拉效果
  19. Excel拆分同一单元格的两行内容为两行(备忘记录)
  20. c语言彩票随机数7位数,随机生成7个不重复的彩票号码 (33选7)

热门文章

  1. html为知笔记模板,为知笔记如何建立模板教程
  2. 三点共线判断方法分析
  3. 计算机中 空间局限性(Spatial Locality)与时间局限性(Temporal Locality)
  4. html5打开新标签,[HTML5] 新标签解释及用法
  5. redis灵魂拷问:为什么响应变慢了
  6. 量子计算(十五):半导体量子芯片
  7. 菜狗centos7.6安装CDH6.1.1(5.13.2)离线集群安装步骤和遇到的各种坑(笔记)
  8. iOS 关于键盘监听
  9. 漫谈分布式游戏服务器
  10. 《给青年的十二封信》2-谈动—朱光潜