uint32_t SPI_RW_Reg(uint16_t CofigReg)
{
delay(10);
readata1=SPIx_ReadWriteByte((uint8_t)(CofigReg>>8));
readata2=SPIx_ReadWriteByte((uint8_t)CofigReg);
readata3=SPIx_ReadWriteByte((uint8_t)(CofigReg>>8));
readata4=SPIx_ReadWriteByte((uint8_t)CofigReg);
readata= (uint32_t)readata4|((uint32_t)readata3<<8)|((uint32_t)readata2<<16)|((uint32_t)readata1<<24);
delay(1000);
//ads_cs_1();
return readata;
}
这个函数我不知道那里有问题 帮忙看一下 谢谢
Johnsin Tao:
Hi
可以直接通过接口时序来确认看写入是否正确,再调整程序。
Carter Liu:
从这个函数看你是在读数据?写入命令的时序图用示波器看了没有
Vio Liu:
Fubo你好,
请问CS拉高拉低是在哪个函数里面实现的?
我在ADS1118的datasheet里面只看到了有16位与32位数据的读写。你的SPIx_ReadWriteByte函数是针对一个8位的数据进行操作的,ADS1118并不支持这样的读写方式。
请检查。祝一切顺利!
user4164237:
回复 Vio Liu:
您好,我的思路如下:
#define AD_SPI1_CS PBout(3)// PB3#define AD_SPI1_SCLK PBout(13)// PB13#define AD_SPI1_MISO PBout(14)// PB14#define AD_SPI1_MOSI PBout(15)// PB15
SCLK,MISO,MOSI 3个角的定义和初始化 还有SPI通信的参数设定
SPI_InitTypeDef SPI_InitStructure;void SPIx_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB1Periph_SPI2, ENABLE ); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //时钟,我用的是GPIOA,和GPIOB,所以时钟GPIOA和GPIOB时钟开启,IO口复用AFIO时钟开启,我用的是SPI2,所以SPI2时钟开启 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIOB13为SCLK,GPIOB14为MISO,GPIOB15为MOSI GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //SPI发送接收16位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //第二个跳变沿数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号为软件控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预分频256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); //根据制定的参数初始化 SPI_Cmd(SPI2, ENABLE); //SPI2使能 SPIx_ReadWriteByte(0x85eb); }
CS片选信号的定义初始化
void SPI_ADS_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SPI CS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_4); SPIx_Init(); //SPI初始化}
int main(void){ u8 a=0; ADS_InitTypeDef ADS_InitStructure; GPIO_Configuration(); //GPIO初始化 USART1_Configuration(); //串口初始化 SPIx_Init(); //SCLK,MISO,MOSI 3个角的定义和初始化 还有SPI通信的参数设定 SPI_ADS_Init(); //CS片选信号的定义初始化
while(1) { SPI2->CR2 |= SPI_I2S_IT_RXNE; // SPI2->DR = V2In2_3ADC; while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)) //loop until DOUT/DRDY set low { printf("\n\r The Value is no ready \r"); }
AD_SPI1_CS=0; //CS信号片选为0 a=SPIx_ReadWriteByte(0xc9eb); //read data
delay(20);
AD_SPI1_CS=1//CS信号片选为1
printf("\n\r The Value is %08x \r",a); }}
//SPIx 读写一个字节//TxData:要写入的字节//返回值:读取到的字节uint32_t SPIx_ReadWriteByte(uint16_t TxData) 函数说明{ u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存非空标志位 { retry++; if(retry>200)return 0; }
SPI_I2S_SendData(SPI1, TxData); //通过外设SPIX发送一个数据(ST官方库提供的函数) retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); //·返回通过SPIX最近接收的数据 (ST官方库提供的函数)}
大哥 我不知道我的问题出在那个地方 帮我分析一下 谢谢 我用的是STM32单片机的硬件SPI (意法半导体)
Vio Liu:
回复 user4164237:
程序我大概看了一下,怎么没发现你关于拉高CS脚的操作?
你用示波器测一下CS、CLK、DATA这几个引脚的波形看一看?
user4164237:
回复 Vio Liu:
刘工,我把程序中CS拉高了 程序中我标了颜色
AD_SPI1_CS=0; a=SPIx_ReadWriteByte(0xc9eb); //read data delay(20); AD_SPI1_CS=1;
CS有波形,很明显的矩形方波,但CLK,和DATA这些角都是没有波形的,数据没有写进去
Vio Liu:
回复 user4164237:
Hi Fubo,
我花了好久好久仔细检查了一下你的代码。累死了,下次贴代码的时候最好稍微花点时间排下版这样别人也会更愿意去花时间看。
发现了这几个问题:
第一,你的SPI的寄存器设置为第二个跳变沿数据被采样,而实际上因为默认CLK为低电平,而你看Datasheet中,CLK上升沿的时候数据被读入ADS1118中,所以应该是第一个跳变沿数据被采样。请确认。
第二,也是最关键的是,你在初始化的时候都是对SPI2做的操作,而在程序的最下方,SPIx_ReadWriteByte这个函数在实现的时候,里面n多操作都是对SPI进行的。这应该是导致你看不到CLK以及DATA的数据的关键。请检查。
如果有最新的进展,或者调试成功,记得来这里更新一下进度哦~期待你的好消息
user4164237:
回复 Vio Liu:
SCK,MISO,MOSI定义,SPI通信参数设定 ADS1118 SCK时序 是第一个上升沿获取数据
void SPIx_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE ); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能IO口复用时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //16位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟悬空高 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第一个时钟延 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件管理 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //波特率预分频256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC计算的多项式 SPI_Init(SPI1, &SPI_InitStructure); //初始化SPI寄存器 SPI_Cmd(SPI1, ENABLE); //SPI使能}
片选信号CS定义和初始化
void SPI_ADS_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //SPI CS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB,GPIO_Pin_3); SPIx_Init(); //初始化SPI}
/*配置寄存器,将指令写入配置寄存器,采样转换完成*/void ADS1118_ADS_Config(unsigned int temp_config_value){ unsigned int Config_Value; Config_Value = temp_config_value; AD_SPI1_CS=0; // Set CS low delay(20); // Wait for slave to initialize ADS1118_WriteSPI(Config_Value,1);// 0为连续模式,转换的数据放入寄存器 delay(20); // Wait for slave to initialize AD_SPI1_CS=1; // Set CS high }
/*转换,写入config寄存器*/void ADS1118_WriteSPI(uint config,unsigned char mode){ uint temp; uchar bit_ctr; AD_SPI1_CS=0; // MOSI_L;//DINÀ拉低,到clk为高(低)时输入 if(mode==1)temp = config | 0x8000;//mode==1,读数据并开始下次转换(OS位置为高) // __delay_cycles(20);//等待OS置高后数据的转换(860sps) // temp &=0x7FFF;//OS置0转换完成 for(bit_ctr=0;bit_ctr<16;bit_ctr++) // 16位配置写入config,DIN后开始转换 { AD_SPI1_SCLK=0; // ..then set SCK low again delay(20); if(temp&0x8000) AD_SPI1_MOSI=1; else AD_SPI1_MOSI=0; AD_SPI1_SCLK=1; // Set SCK high.. delay(20); temp = (temp << 1); // if(MISO) temp++; } AD_SPI1_SCLK=0; delay(20); AD_SPI1_CS=1; delay(20);}
/*将数据读出(DOUT)*/uint ADS1118_ADS_Read(void){ unsigned int Data=0; int i; int a[16]; AD_SPI1_SCLK=1; if(!AD_SPI1_MISO) {//如果DRDY为低,转换完成,则开始读取 for(i=0;i<16;i++) { AD_SPI1_SCLK=0; delay(50);//clk高延时 if(AD_SPI1_MISO) a[i]=1; else a[i]=0;
AD_SPI1_SCLK=1; delay(20);//clk低延时 Data=Data*2+a[i]; } } //__delay_cycles(1600);
//CS_H; return Data;}
main函数中如下:
int main(void){ uint a; ADS_InitTypeDef ADS_InitStructure; RCC_Configuration(); NVIC_Configuration(); USART1_Configuration(); SPIx_Init(); SPI_ADS_Init(); LED_Init(); while(1) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区为空 ADS1118_ADS_Config(0xd5eb); //read data delay(10); a=ADS1118_ADS_Read(); delay(20); printf("\n\r The Value is %08x \r",a); } }
刘工,u8 SPIx_ReadWriteByte(u8 TxData) 这个函数也不能用,是8位的,我重新写了几个函数,奇怪的是始终没有波形,数据也一直是0,我用JLINK在线调试,始终发现返回值a一直是0,百思不得其解
Vio Liu:
回复 user4164237:
您好,在ADS1118_ADS_Read函数中,你是想使用软件模拟SPI总线的时许吗?如果是,那么在初始化的时候应该将对应的引脚初始化为普通的IO
user4164237:
回复 Vio Liu:
刘工,我采集到了数据000055eb