ADS1256问题分析:
从理论和官方上说的来看:选择单端输入可以采集到±5.0v的电压,我一开始选用官方例程STM32F103的发现选用单端老是采集不到负电压。
我的分析思路是这样的:先看一下这个计算过程有没有问题(但是这个没有理论知识其实发现不了什么问题,只能是对比一下其他例程)、然后检查了一下引脚是不是有没接好的(发现是没有的)、最后就是问问实验室的小伙伴(他们都以为我mode模式这些没选对)
后面我就选择换一个例程试一下,一下子就可以了。
我这里自己分析了一下,其中可能存在的问题:引脚初始化出现外设冲突了。
void ADS1256_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化io口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_8| GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RST_L;
Delay_1ms(1);
RST_H;
Delay_1ms(100);
CS_H;
SCLK_L;
DIN_H;
}
(这是采集不到负电压的引脚初始化)
为什么说是引脚冲突呢?我一开始有这个想法是因为例程里面有LCD初始化和显示字符串,库函数没问题,但是初始化可以,显示字符串没有。
我看了一眼官方给的引脚分配图:
这个初始化的很多引脚其实都和这里面的不建议使用撞上了
这个也是我现在晚上时间写分析才想到的,当时没有联想到这一块。后面有时间可以再去验证一下这一块。这个究竟是不是引脚和这里面列出来的的冲突了,才导致一系列的问题
后面换了一个初始化函数就没有问题了
void ADS1256_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
RST_L;
Delay_1ms(1);
RST_H;
Delay_1ms(100);
CS_H;
SCLK_L;
DIN_H;
}
我查了一下表格,发现这些引脚都没冲突,具体一点是我没有外接oled外设,不冲突
所以,以后就是要养成,配置GPIO和看别人的代码的时候关注一下这个有没有和官方函数冲突
养成看这个表格的习惯
还有一个今天学到的就是,这个.c和.h中的编程习惯很值得我学习
具体来说:
#ifndef _ads1256_H
#define _ads1256_H
#include "stm32f10x.h"
/* 寄存器地址, 后面是复位后缺省值 */
#define REG_STATUS (0) // x1H 状态寄存器
#define REG_MUX (1) // 01H 输入多路复用器控制寄存器
/* 命令定义: TTable 24. Command Definitions --- ADS1256数据手册第34页 */
#define CMD_WAKEUP (0x00) // Completes SYNC and Exits Standby Mode 0000 0000 (00h) 完成SYNC并退出待机状态
#define CMD_RDATA (0x01) // Read Data 0000 0001 (01h) 读取数据
#define PGA_1 0x00
#define PGA_2 0x01
extern uint32_t ADS1256_GetAdc(uint8_t channel);
extern void ADS1256_CfgADC(uint8_t gain, uint8_t drate);
#endif
这种将置位电平和一些有关这个模块的寄存器和命令写在.h中,这样查找起来很方便。
/*
*********************************************************************************************************
* 函 数 名: ADS1256_Send8Bit
* 功能说明: 向SPI总线发送8个bit数据。 不带CS控制。
* 形 参: _data : 数据
* 返 回 值: 无
*********************************************************************************************************
*/
void ADS1256_Send8Bit(uint8_t data)
{
uint8_t i;
/* 连续发送多个字节时,需要延迟一下 */
Delay_ns(250);
Delay_ns(250);
/* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns */
for(i = 0; i < 8; i++)
{
if (data & 0x80)
{
DIN_H;
}
else
{
DIN_L;
}
SCLK_H;
Delay_ns(250);
data <<= 1;
SCLK_L; /* <---- ADS1256 是在SCK下降沿采样DIN数据, 数据必须维持 50nS */
Delay_ns(250);
}
}
.c文件和这样列出来一个说明,然后我就现用了
/*
*********************************************************************************************************
* 函 数 名: Srd_05VDC_Init
* 功能说明: 初始化继电器,用相关的引脚来控制选通
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void Srd_05VDC_Init(void)
{
//定义一个结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
//配置引脚:设置为PE0推挽输出
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//开启时钟
GPIO_Init(GPIOE, &GPIO_InitStructure);
Srd_H; //初始默认是:常闭
#ifndef _SRD_H
#define _SRD_H
#include <stm32f10x.h>
/* 命令定义: 引脚、高低电平 */
#define Srd (GPIOE,GPIO_Pin_0)
#define Srd_L GPIO_ResetBits(GPIOE , GPIO_Pin_0)
#define Srd_H GPIO_SetBits(GPIOE , GPIO_Pin_0)
void Srd_05VDC_Init(void);
#endif
学习和使用串口屏问题:
因为这次输出的信息很多,我觉得2.8寸的LCD不够用,所以就用上了陶晶驰的串口屏。
今天速成了一下基础教学,看了他们在B站的教学视频。
我现在就是会用一些基本操作:
页面转化:弹起和按下事件中写入page x(转化回来其实就是类似的,逆向思维)
赋值改变:文本就是tx.txt="xxx"、数字就是nx.val=xxx(这个注意不能多加空格、文本的文字要在字库之内才可以显示、数字不能超出范围)
通过调试输入,来实现调试:改改赋值之类的
但是因为我最后是要通过单片机来控制修改数据,肯定是要通过串口来和这个进行通信,因为USART1已经用来和串口调试助手通信了,我就选用USART3来进行通信
//串口三的初始化:用来和串口屏进行通信
//初始化引脚、串口3的信息、中断服务配置
void uart3_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//时钟GPIOB、USART3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
//USART1_TX PB10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//USART1_RX PB11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断
USART_Cmd(USART3, ENABLE); //使能串口
}
这些就是基本配置了,然后看网上的代码有给的发送函数之类的,我就直接拿来用了。
sprintf((char*)buf,"page1.n0.val=%d",res);
//printf("%s\n",buf);
HMISends((char*)buf);
HMISendb(0xff);
核心就是:将buf数组强转到char类型,然后赋值,通过发送函数发送过去,最后固定发送0xff结束
我其实今天是卡在这个HMISends中的每一步都没问题,但是结束就没有跳到下一步了(我这里使用led1的点亮来判断到底是到了哪一步),晚上想了想感觉是卡在中断服务助手里面。
所以我发现,自己对串口的理解真的还是很浅,就是串口的执行过程,我其实还是没有太懂。
具体一点就是应该去加深一下,串口这个一整个流程中代码是怎么跑的,去看例程里面自己之前没有注意到的细节。
但是这个发送的语法,有效性也有待检测。
发现问题,分析问题,解决问题。
这个能力我还是有待提升。
最后说说今天get到一个初始化的小点:
之前学习RDA5820的时候,中间就有一个whlie循环是在等5820初始化完成才往下跑代码。
今天晚上和硬件测试4051和Srd继电器的时候,我发现不管我怎么改变控制位,输出就是没有变化,我还以为是自己运气爆棚了,这硬件品控问题这么快就给我碰到了。
后面发现,一些基本的闪烁指示灯都没有亮,我就想到可能是初始化都没有
出现这个问题可能是因为,我把ADS1256初始化代码放在前面,但是又没有接入单片机的引脚中,这样可能就导致了初始化失败。
void PeripheralInit(void)
{
SystemInit(); //系统函数初始化
Delay_1ms(100); //等待稳定
//Srd_05VDC_Init(); //继电器初始化控制引脚为:PE0
Delay_50ms(1);
CD4051_Init();
Delay_1ms(10);
ADS1256_GPIO_Init(); //ADC GPIO初始化
USART_Configuration(); //配置串口波特率为115200
Delay_5ms (10);
}