最近要用52单片机读取PT100温度探头和K型热电偶的温度,在设计并焊接完硬件电路之后,发现用C语言读取具体的温度是个麻烦事。具体来说就是不知道怎么用C语言根据芯片的时序图编写驱动,所以也就不知道怎么读取AD芯片和Max6675芯片的数据。要完成这个工作,实际上要做一件横跨硬件电路设计、制作、驱动编写、纯C软件编写的工程,更进一步的话还需要涉及到PCB板的设计,对于我这个硬件新手来说有不小的难度。在完成这些工作之后 (没有设计PCB板),我特意写这篇文章,用来描述根据时序图写C语言驱动的流程,作为对这份工作的纪念,也希望能为后来者提供一点帮助。

对于PT100温度探头,我采用桥式电路检测探头的电阻,电阻信息被转化成电压信号,并用OP07运算放大器对电压信号进行放大。OP07的输出电压用ADS7822芯片进行模数转换。由于本文只涉及C语言驱动的编写,所以这里不贴具体的电路图了。下面是ADS7822工作的时序图:

其中CS是片选,当CS从1跳变为0时,ADS7822开始工作。
DCLOCK是时钟,默认有可能是0或1。
Dout是ADS7822的输出结果。

初始化:
由于在CS=0之后,DCLOCK从0跳变到1就意味着开始计数了。所以一定要在CS设置为0之前先把DCLOCK设置为0。这一点从下表中Tcsd的描述:CS falling to DCLOCK low也可以看出来。


下面三行是ADS7822的初始化

//ad_cs = 1; //驱动代码最后就是ad_cs = 1,所以这里可以省略这个语句
ad_dclock = 0;
//时序图上ad_dout=1,但实际上ad_dout是硬件自己决定变化的,而不是用C语言决定的
//ad_dout = 1;

开始工作:
CS = 0表示ADS7822开始工作。
之后DCLOCK经历2次脉冲 (从低电平跳转到高电平,并保持到高电平结束),这期间Dout保持高电平。
DCLOCK经历1次脉冲,Dout输出一个无效位。
用代码表示:

ad_cs = 0;//启动AD转换
ad_dclock = 1;
ad_dclock = 0;
ad_dclock = 1;
ad_dclock = 0;
ad_dclock = 1;

DCLOCK从高电平变成低电平,完成这个语句后,Dout正处于一个稳定的有效数据位,单片机可以读取数据。DCLOCK从低电平变成高电平时,Dout的有效数据结束,即将输出下一个数据。用代码表示:

ad_dclock = 0;
j = (uint)(ad_dout); //读取数据
ad_dclock = 1;

这个过程一共要进行12个循环,输出12位有效数据。这里有一个问题:最先输出的一位数据是最高位还是最低位?关于这个问题,需要参考我的前一篇文章:查找算法:逐次逼近。根据这篇文章,我们可以知道,第一个输出的数据能表示2048,第二个输出数据表示1024,第三个输出数据表示512…,最后一个输出数据表示1。由此,我们可以知道最先输出的一位数据是最高位。因此,每循环一次,原有数据就要左移一位。所以这12轮的循环用C语言可以表示为:

result = 0;
for(i = 0; i <= 11; i++) //读取采样数据
{//时钟低电平的时候,dout处于稳定的状态,这个时候可以读取doutad_dclock = 0;   j = (uint)(ad_dout); //读取数据,并转化成uint类型result = result << 1; //原有数据左移一位result = result | j; //数据移位后与前面数据相或ad_dclock = 1; //时钟高电平。准备输出下一位数据
}

结束工作:
CS拉回高电平,恢复初始状态。即:

ad_cs = 1;

返回值:
得到的数据一共有2^12= 4096种可能。如果ADS7822的参考电压为2.5V,则每一份表示2.5/4096V。假设二进制结果为1111101000,换成十进制为1000,就表示1000 * 2.5 / 4096 = 0.6104V。

所以读取ADS7822的总体代码为:

uint readADS7822()
{uint result, j;//初始化//ad_cs = 1; //驱动代码最后就是ad_cs = 1,所以这里可以省略这个语句ad_dclock = 1;//时序图上ad_dout=1,但实际上ad_dout是硬件自己决定变化的,//ad_dout = 1; ad_cs = 0;//启动AD转换ad_dclock = 1; ad_dclock = 0;ad_dclock = 1; ad_dclock = 0;ad_dclock = 1;//工作状态result = 0;for(i = 0; i <= 11; i++) //读取采样数据{//时钟低电平的时候,dout处于稳定的状态,这个时候可以读取doutad_dclock = 0;  j = (uint)(ad_dout); //读取数据,并转化成uint类型result = result << 1; //原有数据左移一位result = result | j; //数据移位后与前面数据相或ad_dclock = 1; //时钟高电平。准备输出下一位数据}//结束工作:ad_cs = 1; return result; //返回值,每一份表示2.5/4096V。
}

上述代码虽然能实现读取ADS7822的功能,但是代码比较凌乱。我们需要一个比较好的逻辑:依次进行初始化、完整的读取数据、结束读取、处理数据、返回等5个部分。而不是直接忽略掉部分无效数字,另外我们再删掉一些重复的代码,就可以得到最终的驱动程序。

//这是ADS7822的C语言驱动程序
unsigned int read_ADS7822()
{int i;//定义数据读取次数的变量uint j;//定义采样数据暂存单元uint result; //定义采样数据储存单元,16位数据//初始化ad_dclock = 1;//开始采集数据ad_dclock = 0; //ad_dclock在CS之前设置为低电平ad_cs = 0; //启动AD转换 for(i = 0; i < 15; i++) //读取采样数据,一共15个循环{ad_dclock = 0; //送读取脉冲       j = (uint)(ad_dout); //读取数据result = result << 1;     //总数据移位result = result | j; //总数据移位后与前面数据相或   ad_dclock = 1;}//读取数据完毕,恢复初始化工作ad_cs = 1; //一次采样完成,片选设置为高电平 //处理数据//16位的数据,最高位为0,接着三位没有意义,剩下12位是有效数字//所以要用下面两行代码除去最高的4位数据。result = result << 4; result = result >> 4;return result; //返回采样值,result个2.5/4096V
}

通过ADS7822读取到放大运算器的输出电压后,我们就可以用电压值推算出PT100的电阻值。接着根据电阻值去查表,就可以得到当前的温度了 (当然,这个过程也是软件完成的)。将这个温度与煤油温度计进行对比,发现精度较高,误差 < 1℃。

第二个例子是用K型热电偶测温。
我买的K型热电偶测温用MAX6675芯片驱动,MAX6675芯片通过5根线与单片机连接。MAX6675芯片已经帮我们进行了温度补偿,所以,我们可以读取MAX6675芯片获得温度值。

MAX6675芯片的时序图如下:


说明:
CS是片选,CS从1跳变为0表示MAX6675芯片开始工作。
SCK表示时钟
SO输出数据。

初始化:
由于CS从1跳变为0表示MAX6675芯片开始工作,所以在这之前,要把SCK设置为0。代码为:

SCK = 0;//由于最后需要把SCK设置为低电平,所以这个语句可以不要。

工作状态:
CS从1跳变为0表示MAX6675芯片开始工作。
SCK变成高电平时,SO处于有效数字,这时可以用单片机读取数据。读取完之后,SCK设置为0,完成一个时钟脉冲。代码如下:

SCK = 1;
j = SO;
SCK=0;

MAX6675芯片一共要输出16位数据,也就是要循环16次。代码如下:

for(i = 0; i < 16; i++)
{      SCK = 1;  //SCK为高电平时,输出一位数据   dat = dat<<1;  //读取一位数据,默认读到的是0if( SO==1 )   dat = dat|0x01;   //如果SO是高电平,则把读取到的一位数据设置为1SCK = 0;  //得到一位数据后重新把SCK拉低
}

MAX6675芯片的输出的16位数据中,D15是无效位;D2=1表示K型热电偶不在线,D1是MAX6675芯片的标识位,D0是无效位。所以,只有D14~D3这12位是有效数据。根据这些信息,我们继续对得到的信息进行处理:
1、去除dat的最高位:

dat = dat << 1;
dat = dat >> 1;

其中16位的数据左移一位后,得到的仍旧是16位数据,只不过最高位溢出 (丢失)。
2、去除dat的最低三位:

dat = dat >> 3;

数据右移三位,得到的仍旧是16位数据,只不过最低三位溢出 (丢失)。

合并这三条代码:

dat = dat << 1;
dat = dat >> 4;

最后工作:
SCK设置为低电平,其实这里没有必要。
CS设置为高电平。
代码为:

CS = 1;

总的代码为:

unsigned int MAX6675_ReadReg(void)
{ unsigned char i;  //循环变量 unsigned int dat; //16位的正数据,存放从Max6675中得到的数据 CS  = 0;  //片选,低电平有效。Max6675开始工作SCK = 0;  //开始检测温度//时序图上要操作16次,但只有12位有效数据for(i = 0; i < 16; i++)  {      SCK = 1;  //SCK为高电平时,输出一位数据   dat = dat<<1;  //读取一位数据,默认读到的是0if( SO==1 )   dat = dat|0x01;   //如果SO是高电平,则把读取到的一位数据设置为1SCK = 0;  //得到一位数据后重新把SCK拉低  }CS = 1;  //读取数据完成,重新把片选设置为1。//16位的数据左移一位之后,数据仍然是16位,但是最高位溢出dat = dat << 1;  //略去dat的最高位,这一位始终无效//后三位也没有用。但由于刚刚左移了一位,所以要右移4位才能删除原先的低三位//D2 = 1表示热电偶端口;D1是热电偶的标识位,D0无效dat = dat >> 4;return dat; //返回有效数字,单位为0.25度
}

MAX6675芯片得到的是12位数据,精度为0.25度,所以返回的数据是dat个0.25度。可以用result * 0.25表示最终的温度。实测检测结果与煤油温度计的读数很接近,误差 < 1℃。

注:读取MAX6675芯片的程序是厂家赠送的。

总结:
对于 (简单的) 时序图来说,最重要的是弄清初始状态,以及什么时候读取数据。另外,芯片得到的数据有时不是每一位都是有效的,需要根据datasheet中的提示,酌情删除无效位,才能最终得到有效数据。一定要搞清楚从芯片中得到的数据代表了什么,怎样把这些数据转化成自己真正需要的数据。

成本:数字温度传感器DS18B20 << K型热电偶 < PT100 < PT1000。
温度检测范围:K型热电偶 > PT100 > PT1000 > DS18B20。
其中K型热电偶的检测范围为:0~1024℃;PT100和PT1000可以检测0℃以下的温度;PT1000最高可以达到0.1℃的精度。

硬件编程-----根据时序图写C语言驱动相关推荐

  1. 关于读懂时序图写时序

    我们知道,时序图分为理想时序图和实际工作时序图.理想时序忽略了实际高低电平转换时间,而我们实际写程序过程中更希望看到的是实际工作时序图,更清晰明确. 图1 理想时序与实际时序 物理时序图只要保持操作顺 ...

  2. c语言编程求lnx怎么写,c语言里ln怎么写

    C语言写多项式相加怎么写? 分都不给.算了,以前写了个就给你吧./*此程序结构比较清晰,用单链表实现了多项式的加法.具体原理可以参考清华大学严蔚敏数据<结构C语言版>第二章注意:此程序假设 ...

  3. matlab信号时序图,怎么看时序图,电路原理图(转)

    片选:动词,单片机学科词汇,可以理解成选片.很多芯片挂在同一总线上的时候,有一个信号来区别总线上的数据和地址由哪个芯片来处理,这个信号就叫做片选信号CS(chip select).片选这个词即由此而来 ...

  4. 片选,怎么看时序图,电路原理图

        片选:动词,单片机学科词汇,可以理解成选片.很多芯片挂在同一总线上的时候,有一个信号来区别总线上的数据和地址由哪个芯片来处理,这个信号就叫做片选信号CS(chip select).片选这个词即 ...

  5. 片选,怎么看时序图,电路原理图。CE OE WE信号 纳秒

    片选:动词,单片机学科词汇,可以理解成选片.很多芯片挂在同一总线上的时候,有一个信号来区别总线上的数据和地址由哪个芯片来处理,这个信号就叫做片选信号CS(chip select).片选这个词即由此而来 ...

  6. markdown 绘制流程图、时序图、甘特图

    这些复杂图形的绘制都是使用代码块实现的,指定代码块的解析语言,按照响应的绘制语法即可实现. 流程图--指定 mermaid(样式流程图) 或 flow (标准流程图)解析语言 时序图--指定 sequ ...

  7. 片选,怎么看时序图,电路原理图。CE OE WE信号 纳秒

    片选:动词,单片机学科词汇,可以理解成选片.很多芯片挂在同一总线上的时候,有一个信号来区别总线上的数据和地址由哪个芯片来处理,这个信号就叫做片选信号CS(chip select).片选这个词即由此而来 ...

  8. 怎么用c语言写时序图,plc时序图怎么画_plc时序图编程方法

    时序图是描述设备工作过程的时间次序图,也是用于直观分析设备工作过程的一种图形.如电子技术中的触发器.定时器.计数器等均用时序图来描述其工作原理.在plc顺序控制设计法编制梯形图程序时往往是先画出时序图 ...

  9. uml 时序图_程序猿都应学习的语言:看 25 张图学 UML

    作者 | 逸珺 责编 | 屠敏 来源 | 嵌入式客栈 作为程序猿都最好掌握的一门语言,那就是UML(Unified Modeling Language),统一建模语言(UML)是软件工程领域中一种通用 ...

  10. uml 时序图_面向对象设计与统一建模语言UML

    面向对象设计 自从面向对象编程语言在软件开发中成为主流之后,遵循面向对象技术特点的软件设计工作,也一并发展了起来. 首先要提出一个问题,就是设计的工作是要做什么? 它包括的范围其实是很广泛的,从搜集用 ...

最新文章

  1. ios11修改微信步数_小程序同步微信步数
  2. win10版本查看_想知道电脑中安装的win10版本号,用这3招就对了,一键查看
  3. Android 设置按钮为透明
  4. Wicket实战(二)hello world
  5. 1万字说清楚Receiver Operating curve(ROC) 受试者操作特征曲线
  6. SYN-COOKIE
  7. HTML5 浏览器检测
  8. Knowledge-based Systems期刊投稿经历
  9. android解压rar方法,Android以编程方式解压缩RAR文件
  10. Java //PP1.3 编写一个程序,分行显示你的名字、生日、爱好、最喜欢的书及最喜欢的电影。
  11. 网贷风控体系之-风控模型
  12. Windows无法连接到打印机怎么办?快收藏这些正确做法!
  13. 02-表格基本格式以及各个标签的属性、boder/cellpadding/cellspacing的区分、th标签、caption标签
  14. 一起talk C栗子吧(第一百九十三回:C语言实例--DIY less命令二 )
  15. 企业法人如何去申报每个月的个税的呢
  16. Navicat-导航猫
  17. 我的至爱《约翰克里斯朵夫》读书笔记
  18. 安搭Share谈北上广之外——深!
  19. Linux离线安装tensorflow
  20. 《从0开始设计和实现CPU》总线设计(四)之总线从属多路复用器的实现

热门文章

  1. 差分GPS(differential GPS-DGPS,DGPS)
  2. html图片在桌面的路径,桌面路径无法恢复以前的路径
  3. 【C语言】求方程式 ax^2+bx+c=0 的根, 分别考虑: 1、有两个不等的实根 2、有两个相等的实根
  4. ANC降噪耳机量产测试方案
  5. 【图像处理】图像锐化
  6. django商城项目之历史浏览记录
  7. 阿里P6+面试:介绍下观察者模式?
  8. vue 如何对两个文本比较
  9. 阿里云怎样保障客户网络和数据安全的?
  10. Codeforces蓝名紫名黄名纪念贴