本例程采用宏晶的STC8G1K08单片机来检测输出类型为4~20mA PT100传感器的程序,在检测中使用XPT2046作为AD的检测芯片,XPT2046具有4路12位的AD检测输入端,因此最大可检测4路传感器,本例程中我们只使用了其中1路。检测时使用了中值滤波算法。先看一下XPT2046的驱动程序:
/****************************************************************************
*函数名:SPI_Write
*输 入:dat:写入数据
*输 出:无
*功 能:使用SPI写入数据
****************************************************************************/
void SPI_Write(uchar dat)
{
uchar i;
CLK = 0;
delay_us(2);
for(i=0; i<8; i++)
{
DIN = dat >> 7; //放置最高位
dat <<= 1;
CLK = 0; //上升沿放置数据
delay_us(2);
CLK = 1;
delay_us(2);
}
}
/****************************************************************************
*函数名:SPI_Read
*输 入:无
*输 出:dat:读取 到的数据
*功 能:使用SPI读取数据
****************************************************************************/
uint SPI_Read(void)
{
uint i, dat=0;
CLK = 0;
delay_us(2);
for(i=0; i<12; i++) //接收12位数据
{
dat <<= 1;
CLK = 1;
delay_us(2);
CLK = 0;
delay_us(2);
dat|= DOUT;
}
return dat;
}
/****************************************************************************
*函数名:Read_AD_Data
*输 入:cmd:读取的X或者Y
*输 出:endValue:最终信号处理后返回的值
*功 能:读取触摸数据
****************************************************************************/
uint Read_AD_Data(uchar cmd)
{
uint AD_Value;
CS = 0;
delay_us(2);
CLK = 0;
delay_us(2);
SPI_Write(cmd);
delay_us(6);//延时等待转换结果
CLK = 1; //发送一个时钟周期,清除BUSY
delay_us(2);
CLK = 0;
delay_us(2);
AD_Value=SPI_Read();
CS = 1;
return AD_Value;
}
下面是它的头文件:
#ifndef __XPT2046_H_
#define __XPT2046_H_
#include "STC8G.H"
#include "delay.h"
#include<intrins.h>
//---定义使用的IO口---//
sbit DOUT = P1^0; //输出
sbit CLK = P3^4; //时钟
sbit DIN = P3^6; //输入
sbit CS = P3^5; //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif
以下是主程序:
#include "STC8G.H"
#include "delay.h"
#include "uart1.h"
#include "XPT2046.h"
#define voltage 5.00
#define ncnt 127 //采集次数必须为奇数
float sum=0; //浮点型温度值
float val=0; //AD采集到的电压值
unsigned int temd; //排序中间转换变量
unsigned int temp; //用取取缓存中的中间值
xdata unsigned int value_buf[ncnt]; //AD采集存储缓存
int wendu; //整数型温度变量
char count, i,j; //排序计数变量
unsigned char puf[6];
void main()
{
P_SW1 = 0x10;//RXD/P3.0, TXD/P3.1
Uart1_Init();
P1M0 = 0x00; //设置为准双向口
P1M1 = 0X00;
P3M0 = 0x70; //设置为推挽输出
P3M1 = 0X00;
while(1)
{
//temp = Read_AD_Data(0x94);//AIN0
//temp = Read_AD_Data(0xD4);//AIN1
//temp = Read_AD_Data(0xA4);//AIN2
//temp = Read_AD_Data(0xE4);//AIN3
for (count=0; count<ncnt; count++) //连续采集ncnt次
{
value_buf[count]= Read_AD_Data(0x94); //将采集到的数据存到value_buf中
}
for (j=0;j<ncnt-1;j++) //将采集到的数据从小到大排列
{
for (i=0;i<ncnt-j;i++) //通过for循环排列数据
{
if (value_buf[ i] > value_buf[i+1]) //如果前一个元素大于后一个元素
{
temd = value_buf[ i]; //则将大的元素赋值给temd
value_buf[ i] = value_buf[i+1]; //将小值赋给前一个元素
value_buf[i+1] = temd; //将大值赋给后一个元素
}
}
}
temp=value_buf[(ncnt-1)/2]; //取缓存中的中间值
val=temp*voltage/4096.0; //算出当前电压,5.01是AD基准值,跟据实际电压自行修改
sum=((250.00*val)/2.40)-112.50; //根据公式计算出当前温度,公式: T=(250/2.4)*V-112.5
wendu=(int)(sum*10); //将浮点数*10转换为整数型数据
if(wendu&0x8000) //如果温度为负值
{
wendu=((~wendu)&0x7fff)+1; //则取反加1
puf[0]='-'; //加上负数标志位'-'
}
else if((wendu/1000)==0){
puf[0]=' ';
}else puf[0]=wendu/1000+0x30;
if(((wendu/1000)==0)&&((wendu%1000/100)==0)) //如果最高两位都为0
puf[1]=' '; //则不显示
else puf[1]=wendu%1000/100+0x30; //否则正常显示数
puf[2]=wendu%1000%100/10+0x30;
puf[3]='.';
puf[4]=wendu%1000%100%10+0x30;
// Uart1_SendString(puf);
//Uart1_SendChar(temp/256);
//Uart1_SendChar(temp%256);
delay_ms(300);
}
}
原理图: 无
仿真: 无
Keil代码:
PT00串口.7z
(29.44 KB, 下载次数: 25)
|