1> 项目概述
51单片机模拟SPI总线,读取AD转换芯片TSC2046的4路转换值,通过串口发送到PC;
2> 硬件设计
MCU部分:
ADC部分:
下一版硬件设计,把BUSY信号,连接倒逻辑分析仪接口,方便程序分析;
3> TSC2046
3.1> 长啥样?
3.1.1> 封装图-TSSOP16
3.1.2> 引脚图
3.1.3> 内部框图
TSC2046:
XPT2046:
3.2> 会干啥?
TSC2046 有2个功能:
1》触摸屏控制器(差分模式);
2》4路AD转换(单端模式);
3.3> 咋干的?
3.3.1> 数据转换
因为TSC2046的分辨率为12位,所以2^12 = 4096;
3.4> 咋用他?
3.4.1> 硬件设计
引脚功能描述:
参考 其他原理图设计
3.4.2> TSC2046控制命令
3.4.3> 控制命令总结
XP引脚输入: 0b' 1001 0100; // 0x94;
YP引脚输入: 0b' 1101 0100; // 0xD4;
VBAT引脚输入:0b' 1010 0100; // 0xA4;
AUX引脚输入: 0b' 1110 0100; // 0xE4;
4> SPI通信协议
SPI(Serial Peripheral Interface)串行外设接口;
4.1> 长啥样?
4.1.1> 硬件框图
4.1.2> 时序图
4.2> 能干啥?
芯片与芯片之间通信,传输数据;
4.3> 咋干的?
传输格式:
4.3.1> 信号作用
\CS: (Chip Select), 片选信号,用来选择哪个从芯片与主芯片通信;
CLK: (Clock), 时钟信号,整个通信的节拍控制;
MOSI:(Master Output Slave Input),主芯片输出,从芯片输入信号;
MISO:(Master Input Slave Output),主芯片输入,从芯片输出;
4.3.2> 时序解析
空闲态:
/CS = 1; - CLK = 0;- MOSI = 0;- MISO = 1;
起始位: CS拉低;
停止位:CS拉高;
写时序:MOSI放数据,然后 主机在CLK↑上升沿发送数据,循环8次;
BUSY信号:第9个CLK时产生忙信号,告诉主机正在转换数据;
读时序:第10个CLK↓下降沿,从机在MISO上发送数据,循环12次;
总结规律:
1> 主机在CLK上升沿,发送数据在MOSI上;
2> 从机在CLK下降沿,发送数据在MISO上;
4.3.3> 时序参数
4.4> 咋用他?
《程序设计》
5> 程序设计
5.1> 实现功能
51单片机模拟SPI总线,读取AD转换芯片TSC2046的4路转换值,通过串口发送到PC;
5.2> 编程思路
模块化,分层思路,使SPI驱动模块方便的被所以SPI设备调用,如TSC2046,DS1302等等
5.3> SPI驱动
/**
* @brief : SPI write 1 byte
* @cmd : 8bit command
*/
void SPI_Write_Byte(uchar8_t cmd)
{
uchar8_t i = 0;
uchar8_t temp = 0;
for (i=0; i<8; i++) {
ADC_SPI_CLK = 0;
temp = cmd >> 7;
ADC_SPI_MOSI = temp;
cmd = cmd << 1;
ADC_SPI_CLK = 1;
}
}
/**
* @brief : SPI Read 1 byte
* @retval : ADC 1 byte value
*/
uchar8_t SPI_Read_Byte(void)
{
uchar8_t i = 0;
uchar8_t ret = 0;
for (i = 0; i < 8; i++) {
ADC_SPI_CLK = 0;
ADC_SPI_CLK = 1;
ret = ret << 1;
ret = ret | ADC_SPI_MISO;
}
return ret;
}
5.4> TSC2046驱动
/**
* @brief : SPI Read TSC2046 ADC
* @cmd : 8bit command
* @retval : ADC 1 byte value
*/
ushort16_t TSC2046_Read(uchar8_t cmd)
{
ushort16_t val = 0;
// 初始化
ADC_SPI_CS = 1;
ADC_SPI_CLK = 0;
ADC_SPI_MOSI = 0;
ADC_SPI_MISO = 1;
ADC_SPI_CS = 0; // 启动
SPI_Write_Byte(cmd); // 第1个8拍,写命令
val = SPI_Read_Byte(); // 第2个8拍,读第1字节的数据
val <<= 8;
val |= SPI_Read_Byte(); // 第3个8拍,读第2字节的数据
val = val >> 3;
ADC_SPI_CS = 1;
ADC_SPI_CLK = 0;
ADC_SPI_MOSI = 0;
ADC_SPI_MISO = 1;
return val;
}
6> 联调测试
6.1> VBAT的1/4分压
实验过程中发现VBAT引脚采样电压错误,阅读手册后发现VBAT引脚有1/4分压电路