一、 实验要求
- 掌握SPI总线的使用方式
- 掌握xpt2046 AD转换芯片的工作原理
- 掌握SPI总线方式实现基于xpt2046的AD转换
- 掌握PWM控制功率的方式
二、 实验设计
1.整体思路
该程序旨在实现基于 SPI 总线的 XPT2046 芯片的 AD 转换,并利用转换结果在数码管上显示数值,同时通过 PWM 控制实现 LED 灯亮度与 AD 值的联动。整体思路是先进行系统初始化,包括定时器和端口等设置,然后在主循环中不断读取 AD 转换数据,处理数据后更新数码管显示,并根据 AD 值调整 PWM 占空比来控制 LED 亮度。
2.流程图
图1 流程图
3.主要模块设计思路及分析
(1)延时函数(delay)
设计思路:通过循环递减传入的参数i来实现延时功能,当i减为 0 时,延时结束。
分析:这是一个简单的延时函数,用于在需要短暂停顿的地方,如数码管显示时的位选通切换等操作,以确保显示稳定。
(2)数码管显示函数(DigDisplay)
设计思路:通过位选通控制(LSA、LSB、LSC)来依次选择数码管的位,然后将要显示的数据发送到P0端口来显示数字。每个数码管位显示一定时间(通过delay(100)实现)后关闭显示(P0 = 0x00),以避免余晖现象。
分析:这种动态扫描的方式可以利用较少的单片机端口来控制多个数码管显示。然而,在实际应用中,如果扫描速度过快,可能会导致数码管显示闪烁;如果过慢,可能会出现显示拖影。
(3) 数据处理函数(readData)
设计思路:使用一个计数器cnt,当cnt达到 25 时(可以理解为定时触发),调用Read_AD_Data函数读取 AD 转换数据,将数据进行拆分处理后存储到DisplayData数组中用于数码管显示,并根据temp和step计算lightTime用于后续 PWM 控制。每次调用readData函数时,cnt递增,当cnt超过 25 时重新归零。
分析:这种定时读取 AD 数据的方式可以在一定程度上稳定数据更新频率。但如果Read_AD_Data函数执行时间过长或者其他操作导致readData函数执行时间不稳定,可能会影响定时准确性。另外,step的值如果不合理,可能会导致lightTime计算结果不准确,从而影响 LED 亮度调节效果。
(4)中断函数(timer)
设计思路:利用定时器 0 中断(中断号 1),在中断服务程序中,counter递增,当counter达到 100 时重新归零,以此来实现一个循环计数。根据counter和lightTime的比较结果来控制 LED 的亮灭,从而实现 PWM 控制。
分析:通过中断方式实现 PWM 控制可以在不影响主程序流程的情况下,精确地控制 LED 亮度。但需要注意的是,中断函数中的代码应该尽量简洁高效,避免占用过多时间导致其他中断或主程序执行出现问题。如果lightTime的计算不准确或者更新不及时,会导致 PWM 占空比不正确,从而影响 LED 亮度变化不符合预期。
(5) SPI 相关函数(SPI_Write、SPI_Read、Read_AD_Data)
设计思路
SPI_Write函数:在时钟线CLK为低电平时,将数据dat的最高位通过DIN线发送出去,然后将dat左移一位,再将时钟线拉高拉低,模拟 SPI 总线的时钟信号,完成一位数据的传输,如此循环 8 次,完成一个字节的数据写入。
SPI_Read函数:先将时钟线拉低,然后在时钟线上升沿时读取DOUT线上的数据,每次读取一位数据并左移到dat变量中,循环 12 次,完成 12 位数据的读取并返回。
Read_AD_Data函数:先拉低片选信号CS,然后通过SPI_Write函数发送读取命令cmd,接着进行一些时钟信号的操作(可能是为了满足芯片时序要求),再通过SPI_Read函数读取 AD 转换值,最后拉高片选信号CS并返回读取到的 AD 值。
分析
SPI 通信部分是实现与 XPT2046 芯片通信的关键。这些函数的正确性直接影响到 AD 转换数据的获取。在SPI_Write和SPI_Read函数中,时钟信号的控制和数据的传输顺序需要严格按照 SPI 总线协议以及 XPT2046 芯片的要求来实现。如果时序出现偏差,可能会导致通信失败或者数据错误。Read_AD_Data函数中对芯片命令的发送和数据读取的流程也需要与芯片手册一致,否则无法正确获取 AD 转换结果。
(6)主函数(main)
设计思路:首先对定时器 0 进行初始化,设置为工作模式 2,初值为0xa0,并启动定时器(TR0 = 1)。然后进入一个无限循环,在循环中不断调用readData函数读取和处理数据,调用DigDisplay函数显示数据。
分析:主函数是整个程序的核心控制部分,它协调了各个模块的工作。定时器初始化设置了定时中断的参数,影响到 PWM 控制的频率和精度。在主循环中,通过不断更新数据和显示,实现了系统的动态运行。
(7)XPT2046 相关头文件(xpt2046.h)
设计思路:定义了与 XPT2046 芯片通信相关的引脚(DOUT、CLK、DIN、CS)以及函数声明(Read_AD_Data、SPI_Read、SPI_Write),确保在其他源文件中可以正确调用这些函数和使用相关引脚。
分析:头文件提供了一种模块化的编程方式,将与硬件相关的定义和函数声明集中管理,提高了代码的可读性和可维护性。
三、 实现效果
图2 效果图
图3 效果图
图4 效果图
四、总结
1.实验中遇到的问题
LED 不亮问题
问题分析:起初 LED 不亮可能是由于多种原因造成的。硬件方面,可能存在单片机端口配置问题(未正确设置为输出模式)等;软件方面,可能在 PWM 控制逻辑中存在错误,如counter和lightTime的计算错误、中断相关设置问题(包括定时器初值设置不当影响中断频率、中断函数中的逻辑错误等)、Read_AD_Data函数获取的 AD 值错误导致lightTime计算异常等。
解决方法:
在主函数中将 P2.7 配置为输出
P2M0 = 0x00;
P2M1 = 0x00;
但是这种方法受keil版本影响
2.实验总结
通过编写SPI_Write和SPI_Read函数,实现了单片机与 XPT2046 芯片之间基于 SPI 总线的通信,能够正确地向芯片写入命令并读取数据,表明对 SPI 总线的基本使用方式已掌握。根据 XPT2046 芯片的工作原理,成功编写了Read_AD_Data函数来控制芯片进行 AD 转换,并在readData函数中将转换结果进行处理和显示,实现了利用 SPI 总线完成基于该芯片的 AD 转换功能,达到了实验要求。利用定时器中断实现了 PWM 控制,在timer函数中通过改变 LED 的亮灭时间占空比来调节亮度,并且与 AD 转换结果联动,当 AD 值变化时,LED 亮度能够相应改变,成功掌握了 PWM 控制功率的方式。