AD7606 与STM32MINI板SPI通信采集数据,昨天采样两线全双工,读出数据为0000,现在改为一线只读,读出数据与实际接入电压不对...

2019-08-16 22:24发布

采集到数据一直在跳变,换算后与接入电压值也不对应,调了两天也没搞好,请大家看看,帮帮忙
*********************************************************以下是程序代码,希望各位帮忙指正
#include "spi.h"
#include "sys.h"

//PA4、PA5、PA6分别接AD7606CS、SCK/RD,DB7
#define SCK_0()                GPIOA->BRR = GPIO_Pin_5
#define SCK_1()                GPIOA->BSRR = GPIO_Pin_5

void _SPI__Init()
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        SPI_InitTypeDef   SPI_InitStruct;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB|RCC_APB2Periph_SPI1 , ENABLE);

        
  //配置SPI1 : SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//SCK配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//MISO配置
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  //配置片选 IO PA4
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//ƬѡÅäÖÃ
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
        PAout(4)=1;
  PAout(5)=0;
        
                //配置CONVST GPIO */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        PAout(8)=1;
        //配置RANGE  
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        PBout(5)=1;
        //配置REST
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        PBout(7)=1;
                //busy
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//PB6_BUSY 配置
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        
  SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_64;
        SPI_InitStruct.SPI_CPHA=SPI_CPHA_2Edge;//第二个上升沿采集
        SPI_InitStruct.SPI_CPOL=SPI_CPOL_High;
        SPI_InitStruct.SPI_CRCPolynomial=7;
        SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b;//8λ
        SPI_InitStruct.SPI_Direction=SPI_Direction_1Line_Rx;//只读
        SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;//¸高位在前
        SPI_InitStruct.SPI_Mode=SPI_Mode_Master;
        SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;
        SPI_Init(SPI1,&SPI_InitStruct);
        
        SPI_Cmd(SPI1, ENABLE);
        ad7606_SetOS(0);//设置是否过采样
  ad7606_SetInputRange(0);//设置范围
  ad7606_Reset();//硬件复位
  AD_CONVST_HIGH();
        ad7606_StartConv();//开始转换
}




//设置电压范围0代表正负5V 1代表正负10v
void ad7606_SetInputRange(u8  _ucRange)
{
        if (_ucRange == 0)
        {
                PBout(5) = 0;
        }
        else
        {
                PBout(5) = 1;
        }
}

//硬件复位函数
void ad7606_Reset(void)
{

        int i;
        AD_CS_HIGH();
        PBout(7)=0;
        PBout(7)=1;
        for(i=0;i<50;i++) ;
        PBout(7)=0;
}
//开始转换函数
void ad7606_StartConv(void)
{

        AD_CONVST_HIGH();
        AD_CONVST_HIGH();
        AD_CONVST_LOW();
        AD_CONVST_LOW();        /* μíμ&#231;&#198;&#189;50ns */
        AD_CONVST_LOW();
        AD_CONVST_LOW();
//        delay_ms(5);
        AD_CONVST_HIGH();
}

//设置是否过采样函数

void ad7606_SetOS(u8 _ucMode)
{
        if (_ucMode == 1)
        {
                AD_OS2_0();
                AD_OS1_0();
                AD_OS0_1();
        }
        else if (_ucMode == 2)
        {
                AD_OS2_0();
                AD_OS1_1();
                AD_OS0_0();
        }
        else if (_ucMode == 3)
        {
                AD_OS2_0();
                AD_OS1_1();
                AD_OS0_1();
        }
        else if (_ucMode == 4)
        {
                AD_OS2_1();
                AD_OS1_0();
                AD_OS0_0();
        }
        else if (_ucMode == 5)
        {
                AD_OS2_1();
                AD_OS1_0();
                AD_OS0_1();
        }
        else if (_ucMode == 6)
        {
                AD_OS2_1();
                AD_OS1_1();
                AD_OS0_0();
        }
        else        
        {
                AD_OS2_0();
                AD_OS1_0();
                AD_OS0_0();
        }
}
//延时函数
void bsp_spiDelay(void)
{
        u8 i;

        for (i = 0; i<2; i++);
}


//读取8位数据
u8  bsp_spiRead(void)
{

        u8 read=0;
        u8 i;
        for (i = 0; i < 8; i++)
        {  
    SCK_0();//拉低时钟延时
                bsp_spiDelay();
                read<<=1;        
                if(PAin(6)==1)
    {
                  read++;         
                }
    SCK_1();//拉高时钟
                bsp_spiDelay();
        }

        return read;

}
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "spi.h"
#include "led.h"
#include "string.h"
//#include "TIMER.h"
u16 ADC_value1[8];//′&#230;·&#197;8í¨μàêy&#214;μ
float pp[2];
char string[20];
int main(void)
{        
   u8 i;
         SystemInit();
         LED_Init();
          _SPI__Init();
        // _TIMER_Init_(4999,7199);
   delay_init();
         uart_init(115200);
         
         while(1)
         {
                 if(PBin(6)==0)//PB6接busy引脚,判断busy是否为零
                {
       PAout(5)=1;//拉高时钟线
                   AD_CS_LOW();//拉低片选
       for(i=0;i<1;i++)
            {        
              ADC_value1=bsp_spiRead();
                                ADC_value1=ADC_value1*256+bsp_spiRead();
                          pp=(float) ADC_value1/32767*5;
                    printf("%f ",pp);        
            }

      AD_CS_HIGH();//拉高片选
            ad7606_StartConv();//开始转换
                }
                delay_ms(500);
         }
}
[/mw_shl_code]

*********************************************************以上是程序代码,希望各位帮忙指正

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
24条回答
dazalei
2019-08-18 23:04
本帖最后由 dazalei 于 2016-10-16 09:21 编辑
jack he 发表于 2016-10-14 15:39
我记得当时我两种方式都成功了;
1、用SPI2_MISO的话使用SPI_Direction_2Lines_RxOnly;
2、用SPI2_MOSI ...

非常感谢!
我目前的状态是这样的。用ARM的SPI2接收AD7606过来的SPI数据,由于不用给AD7606发送数据,仅用三个片选、时钟和MISO三根数据先。ARM是主设备,AD7606是从设备。SPI1默认连接到FLASH上当缓存,使用SPI2接口。接法如下
开发板                   STM32F407
P3(44)                    PB12                  SPI2_NSS
P3(41)                    PB13                  SPI2_SCK
P3(21)                    PC2                    SPI2_MISO

四种工作模式看了你的讲解我好像有点明白啦   以下是我自己理解你看对不对
主模式下:
SPI_Direction_2Lines_FullDuplex :1 可以是双线双向(即普通的用法MISO+MOSI), 2 也可以是单线单向只发送模式(可以理解为有两条数据线,发送但是不理会接受的数据,当然你也可以不连接接收线miso)
SPI_Direction_2Lines_RxOnly:是单线单向只接收模式,用miso线;
SPI_Direction_1Line_Rx:是单线双向在接收时的配置,只要是主设备模式下,只能使用mosi这根线进行数据接收,也就是ARM接收来自AD7606的数据,而不能用MISO,否则收不到数据;
SPI_Direction_1Line_Tx:是单线双向在发送时的配置,只要是主设备模式下,只能使用mosi这根线进行数据接收,不能用MISO;(上面两种在从模式下均用miso)
以上理解正确吗?

补充一下:
我感觉一般对于只有主从两个设备的话是使用软件NSS,因为不需要多机通讯,在软件时,主设备的内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动,从设备的通过你的cs来驱动。cs的引脚与spi2硬件的相应管脚重合。
——[size=14.6667px]cs的引脚与spi2硬件的相应管脚重合?没有明白。您说的这种设置感觉有点分别设置的感觉。我的理解:硬件NSS,设置ARM主设备,设置ARM NSS引脚高低电平直接控制AD7606的CS管脚,也就是连接 PB12                  SPI2_NSS到AD7606的CS脚上,实际中发现此管脚线上一直是低电平。后来根据你上个跟帖单独把    PB12  作为一个通用GPIO连接到AD7606的片选上。

但是现在依然在SPI-DR中都是小AD值

一周热门 更多>