请教各位大神,用stm32驱动的cs5530,用的是模拟SPI,用串口发到上位机,时而能采集到数,但是大多时候采集的是0.时而采到的数是正确的,猜想还是模拟SPI哪里出现了问题。请问各位大神有什么好的解决办法吗,这个软件调试、时钟和sdi都能正常写指令的,用示波器看 时钟质量非常不好,sdi看不到数据 sdo根本没有。#include "cs5530.h"
#include "delay.h"
#include "sys.h"
//毫秒级延时函数
#define TIME 1
#define SET_ADCS PBout(15)=1;
#define CLR_ADCS PBout(15)=0;
#define SET_ADSCK PBout(12)=1; //spiSCK输出高
#define CLR_ADSCK PBout(12)=0; //spiSCK输出低
#define SET_ADI PBout(14)=1; //MOSI输出高
#define CLR_ADI PBout(14)=0; //MOSI输出低
#define GET_ADO PBin(13) //MISO输入高
void CS5530_PORT_INIT( void ) /* 由于使用软件模拟SPI读写时序,所以进行初始化 */
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); //使能pc端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_12|GPIO_Pin_15; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 对于双向I/O引脚模拟SPI接口,那么必须在此设置SPI_SCS,SPI_SCK,SPI_SDI为输出方向,SPI_SDO为输入方向 */
}
void Write_CS5530(unsigned char Dat)
{
unsigned char Count;
for( Count=0; Count<8; Count++ )
{
if(Dat & 0x80)
{SET_ADI;}
else
{CLR_ADI;}
delay_us(1);
SET_ADSCK;
delay_us(1);
CLR_ADSCK;
delay_us(1);
Dat <<= 1;
}
CLR_ADI;
delay_us(1);
}
//
unsigned char Recive_CS5530(void)
{
unsigned char Count;
unsigned char Dat=0;
CLR_ADI;
delay_us(3);
for( Count=0; Count<8; Count++ )
{
SET_ADSCK;
delay_us(1);
Dat <<= 1;
if( GET_ADO ) Dat |= 0x01 ;
CLR_ADSCK;
delay_us(1);
}
return(Dat);
}
void Write_CS5530_Register(unsigned char Command,unsigned long setData)
{
Write_CS5530( Command );
Write_CS5530( (unsigned char)(setData>>24) );
Write_CS5530( (unsigned char)(setData>>16) );
Write_CS5530( (unsigned char)(setData>>8) );
Write_CS5530( (unsigned char)(setData>>0) );
}
unsigned long Read_CS5530_Register(unsigned char Command)
{
unsigned long temp=0;
Write_CS5530( Command );
temp = Recive_CS5530();
temp = temp << 8;
temp += Recive_CS5530();
temp = temp << 8;
temp = Recive_CS5530();
temp = temp << 8;
temp += Recive_CS5530();
return temp;
}
void Init_CS5530(void)
{
unsigned long temp;
unsigned char i;
// SPI IO 初始化行为
CS5530_PORT_INIT();
CLR_ADSCK;
CLR_ADCS;
delay_ms(100);
// SPI 串口归位
for( i=0; i<20; i++ )
{
Write_CS5530(SYNC1);
}
Write_CS5530(SYNC0);
// 系统复位
Write_CS5530_Register(Write_CONFIG,SYSTEM_RESET); //写配置寄存器写入 CS5530RS 为 1
delay_ms(50);
do
{//检测 RV 是否为 0(复位成功后为 0),如果不为 0 再继续读取配置寄存器
temp = Read_CS5530_Register( Read_CONFIG );
} while( temp & RESET_STATUS );
// 设置偏移寄存器
Write_CS5530_Register(Write_OFFSET,0x00000000);
delay_ms(50);
// 设置增益寄存器
Write_CS5530_Register(Write_GAIN,0x0f000000);
delay_ms(50);
// 设置配置寄存器,设置参考电压,信号极性,字速度等等
//Write_CS5530_Register(Write_CONFIG,0x02004800);
//Delay_ms(50);
temp = 0x00;
temp |= UNIPOLAR_MODE; // 单极性
temp |= LINE_FREQ_50; // 滤波选择缺省滤波字
temp |= DATARATE_25;
temp |= NORMAL_MODE; // 普通操作
temp |= VREF_LOW; // VREF_HIGH 为 2.5V 基准; VREF_LOW 为 1-2.5V 基准
temp |= CR_A0_0;
temp |= CR_A1_0;
temp |= TURN_OFF_300NA; // 不激活电流源
Write_CS5530_Register(Write_CONFIG,temp);
delay_ms(50);
//启动转换
Write_CS5530( START_CONTINUOUS + NORMAL_CONVERSION); // 单次转换
}
// 读取数据转换的结果
unsigned long Get_Ad(void)
{
unsigned long temp;
do //等待转换完成
{
;
}while(GET_ADO);
CLR_ADI;
Write_CS5530( NULL_BYTE ); // 清除串口标志同时选择转换模式(单次连续还是结束单次连续)
temp = Recive_CS5530();
temp = temp << 8;
temp += Recive_CS5530();
temp = temp << 8;
temp += Recive_CS5530();
temp = temp << 8;
temp += Recive_CS5530();
//Write_CS5530( START_SINGLE + NORMAL_CONVERSION); // 单次转换
return temp;
}
#ifndef __CS5530_H__
#define __CS5530_H__
#include "delay.h"
#include "sys.h"
//------------------------------------
//-- CS5530 专有宏定义
#define SYNC1 0xff //串行口初始化序列命令之一
#define SYNC0 0xfe //串行口初始化序列结束命令
#define NULL_BYTE 0x00 //用来清除端口标志位使得转换器保持在连续转换模式
#define CMD_WRITE (0x00<<3) // 写寄存器命令
#define CMD_READ (0x01<<3) // 读寄存器命令
//Command Register
#define Write_OFFSET 0x01 //写偏移寄存器
#define Read_OFFSET 0x09 //读偏移寄存器
#define Write_GAIN 0x02 //写增益寄存器
#define Read_GAIN 0x0a //读增益寄存器
#define Write_CONFIG 0x03 //写配置寄存器
#define Read_CONFIG 0x0b //读配置寄存器
#define START_SINGLE (0X00<<6) //单次转换
#define START_CONTINUOUS (0X01<<6) //连续转换
#define NORMAL_CONVERSION (0x80+0x00)//转换命令
#define SYSTEM_OFFSET_CAL 0x85 //执行系统偏移校准
#define SYSTEM_GAIN_CAL 0x86 //执行系统增益校准
//Configuration Register
#define STANDBY_MODE (0x00L<<31) //待机模式
#define SLEEP_MODE (0x01L<<31) //休眠模式
#define POWER_SAVE_MODE (0x01L<<30) //节电模式
#define NORMAL_MODE (0x00L<<29) //正常操作
#define SYSTEM_RESET (0x01L<<29) //激活一个复位周期复位后自动清0
#define RESET_STATUS (0x01L<<28) //复位有效系统已复位只读
//#define SHORT_INPUTS (0x00L<<27) //输入正常输入个通道输入不断接
#define SHORT_INPUTS (0x01L<<27) //输入正常输入个通道输入不断接
#define VREF_HIGH (0x00L<<25) //参考电压 2.5~((VA+)-(VA-))V
#define VREF_LOW (0x01L<<25) //参考电压 1~2.5V
#define CR_A1_0 (0x00L<<24)
#define CR_A1_1 (0x01L<<24)
#define CR_A0_0 (0x00L<<23)
#define CR_A0_1 (0x01L<<23)
#define LINE_FREQ_60 (0x00L<<19) //滤波数率选择缺省输入字
#define LINE_FREQ_50 (0x01L<<19) //输出字数率及相应滤波器特性乘以系数5/6
#define DATARATE_100 (0x00L<<11) //字数率不同位就不同
#define DATARATE_50 (0x01L<<11)
#define DATARATE_25 (0x02L<<11)
#define DATARATE_12P5 (0x03L<<11)
#define DATARATE_6P25 (0x04L<<11)
#define DATARATE_3200 (0x08L<<11)
#define DATARATE_1600 (0x09L<<11)
#define DATARATE_800 (0x0aL<<11)
#define DATARATE_400 (0x0bL<<11)
#define DATARATE_200 (0x0cL<<11)
#define DATARATE_BIT (0x0fL<<11)
#define BIPOLAR_MODE (0x00L<<10) //极性选择双极性模式
#define UNIPOLAR_MODE (0x01L<<10) //极性选择单极性模式
#define TURN_OFF_300NA (0x00L<<9) //不激活电流源
#define TURN_ON_300NA (0x01L<<9) //激活电流源 300ma
void Init_CS5530(void);
unsigned long Get_Ad(void);
//void CS5530_PORT_INIT( void );
#endif
|