一、?实验要求
实验目的:
实验内容:
学习xpt2046 AD转换芯片的工作原理,利用SPI总线实现基于该芯片的AD转换,调节滑动变阻器将AD转换的结果显示在数码管上,同时利用PWM控制方式实现LED灯的亮度联动,当AD结果增大时,亮度增加,反之,亮度减小。
二、?实验设计
1.整体思路
初始化: 定义相关的IO口和数据类型。
SPI通信: 实现SPI协议的写和读操作,用于与XPT2046通信。
读取AD数据: 通过SPI通信,发送命令并读取XPT2046返回的AD转换数据。
显示数据: 将读取到的数据显示到数码管上。
2.流程图
图 1?算法设计流程图
一、SPI_Write函数:
通过循环将8位数据一位一位地发送到DIN线上。
利用CLK的上升沿将数据放置到DIN上。
二、SPI_Read函数:
通过循环从DOUT线上一位一位地读取12位数据。
利用CLK的下降沿将数据从DOUT读取进来。
三、Read_AD_Data函数:
通过SPI通信发送命令给XPT2046。
等待转换完成,并清除BUSY标志。
读取转换后的AD数据。
四、DigDisplay函数:
用于控制数码管的显示。
通过循环和switch语句选择要点亮的数码管,并发送要显示的数据。
五、readData函数:
这个函数似乎没有完全给出,但从名称来看,它应该是用于读取某种数据(可能是触摸屏的数据)并可能进行进一步的处理。
三、?实现效果
图 2?小于1000显示3个灯
图 3?大于1000显示4个灯
图 4?大于2000显示5个灯
图 5?大于3000显示6个灯
代码主要实现了与XPT2046触摸屏控制器的SPI通信,能够发送命令并读取转换后的AD数据,然后将数据显示到数码管上。需要注意的是,代码中的readData函数没有完全给出,可能需要根据实际需求进行完善。
附录:
#ifndef ??__XPT2046_H_
#define ??_._XPT2046_H_
//---包含头文件---//
#inclu.de<reg52.h>
#include<intrins.h>
//---.重定义关键词---//
#ifndef uchar
#defin.e uchar unsigned char
#endif
#ifndef uint
#define uint ?unsigned int
#endif
#ifndef ulong
#define ulong ?unsigned long
#endif
typedef unsigned int u16; ??//对数据类型进行声明定义
typedef unsigned char u8;
//---定义使用的IO口---//
sbit DOUT = P3^7; ????//输出
Sbi.t CLK ?= P3^6; ????//时钟
sbit DIN ?= P3^4; ????//输入
sbit CS ??= P3^5; ????//片选
sbit LSA=P2^2;
Sbit.?LSB=P2^3;
sbit LSC=.P2^4;
sbit LS5=P2^5;
sbit L.S6=P2^6;
sbit LS7=P2^7;
u8 DisplayData[8];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
#endif
void SP.I_Write(uchar dat)
{
????uchar i;
????CLK = 0;
????for(i=0; i<.8; i++)
????{
????????DIN = dat >> 7; ????//放置最高位
????????dat <<= 1;
????????C.K = 0; ???????????//上升沿放置数据
????????CLK = 1;
????}
}
uint SPI_Read(void)
{
????uint i, dat=0;
????CLK = 0;
????for(i=0; i<12; i++) ????//接收12位数据
????{
????????dat <<= 1;
????????CLK = 1;
????????CLK = 0;
????????dat |= DOUT;
????}
????Ret.urn dat;
}
uint Read_A.D_Data(uchar cmd)
{
????Uch.ar i;
????uint AD_Value;
????CLK = 0;
????CS ?= 0;
????SPI_Write(cmd);
????for(i=6; i>0; i--); ????//延时等待转换结果
????CLK = 1; ?????//发送一个时钟周期,清除BUSY
????_nop_();
????_nop_();
????CLK = 0;
????_nop_();
????_nop_();
????AD_Value=SPI_Read();
????CS = 1;
????return AD_Value; ???
}
void delay.(u16 i)
{
while(i--);
}
void DigDi.splay()
{
????u8 i;
????for(i=0;i<4;i++)
????{
????????switch(i) ???//位选,选择点亮的数码管,
????????{
????????????case(0):
????????????????LSA=0;LSB=0;LSC=0; break;//显示第0位
????????????case(1):
????????????????LSA=1;LSB=0;LSC=0; break;//显示第1位
????????????case(2):
????????????????LSA=0;LSB=1;LSC=0; break;//显示第2位
????????????case(3):
????????????????LSA=1;LSB=1;LSC=0; break;//显示第3位
????????}
????????P0=DisplayData[3-i];//发送数据
????????delay(100); // 延时
????????P0=0x00;//消隐
????}
}
void readData()
{
????int cnt,te.mp,lightTime,step;
????if(cnt == 25)
????{
????????cnt = 0;
????????temp = Read_.AD_Data(0x94); ?????// 电位器
????????DisplayData[0]=smgduan[temp/1000];//千位
????????DisplayData[1.]=smgduan[temp%1000/100];//百位
????????DisplayData.[2]=smgduan[temp%1000%100/10];//十位
????????DisplayData[3]=smgduan[te.mp%1000%100%10];//个位 ??????
????????lightTime = temp / step; ???// 设置亮灯的时间
????}
????cnt ++;
if(temp<1000){
LSA=0;
LSB=0;
L.SC=0;
LS5=1;
LS6=1;
LS7=1;
}
else if(temp>=10.00&&temp<2000){
LSA=0;
LSB=0;
LSC=0;
LS5=0;
LS6=1;
LS7=1;
}
else if(temp>=2000&&temp<3000){
LSA=0;
LSB=0;
LS.C=0;
LS5=0;
LS6=0;
LS7=1;
} ?
else if(temp>=3000){
LSA=0;
LSB=0;
LSC=0;
LS5=0;
LS6=0;
LS7=0;
} ????
}
void main() {
????TMOD = 0x02; // 开启中断方式2
????TH0 = 0xa0; // 0.1us
????TL0 = .0xa0;
????TR0 = 1;
????ET0 = 1;
????EA = 1;
????while(1) {
????????readData(); ????// 数据处理
????????DigDi.splay(); ??//数码管显示
????}
}