×
嵌入式 > 技术百科 > 详情

基于MSP430的ADS7841驱动程序

发布时间:2020-06-20 发布时间:
|
师姐(博士)反向设计了ADS7841芯片。为了测试其稳定性和精度,所以帮忙写了这个驱动程序。最初是师兄用FPGA写的,但读出来的数据差距太大,所以我就用430单片机帮忙搞了一个!但这个程序调试的并不顺利,简直就是痛苦,我昨天中午和晚上都没吃饭!首先碰到I/O口坏的情况,还有就是这个芯片的 DATASHEET关于读数的说明是错的,害人不浅!据datasheet解释是等待busy信号为低才开始读数,其实这个时候已经晚了,会漏掉一位。所有上面这些问题我是借助逻辑分析仪看出来的,把抓出来的时序一点点的分析,终于发现了读数方面DATASHEET的漏洞。还有就是她没提写数据和读数据分别应该在时钟的什么沿触发。实在让人郁闷~!~正常应该在下降沿写指令,上升沿读数据!
折腾了一天才有结果,如果不是逻辑分析仪的帮忙,我估计死都不知道怎么死的。。
好了,情况说明了,下面是代码部分。
*****************************************************************************
** 函数原型:unsigned int ADS7841_Read_Data(unsigned char Channel);
** 功    能:SPI总线的A/D ADS7841 驱动程序
** 入口参数:unsigned char Channel   表示选择读取通道
** 出口参数:unsigned int   返回所读取得12位数据。
** 说    明:ADS7841为12位A/D,先对其进行设置:数据位D0---D7,其中D0---D1是
**           设置ADC的功耗模式,D2是模拟输入通道设置,H为4个单通道,L为两个
**           差分输入,D3为mode,当mode(pin)接地时为12位采样方式,接高电平时
**           mode为1时8位采集,为0时12位采集,D4---D6为输入通道选择,D7为起始位
** 作   者: 沉思的鱼
** 日   期: 2007年11月06日
**-----------------------------------------------------------------------------
** 修 改 人:
** 日   期:
*******************************************************************************/
#include
#define uint      unsigned int
#define uchar       unsigned char
#define ADS_S       0x80    //命令起始位
#define ADS_MODE    0x08    //模式选择。MODE端选择直接接高电平,此位不用设置
#define ADS_S_D     0x04    //输入方式选择
#define ADS_POWER   0x00    //是否允许掉电
#define DIR_CS      P3DIR|=BIT0
#define ADS_CS_1    P3OUT|=BIT0
#define ADS_CS_0    P3OUT&=~BIT0 //片选
#define ADS_DIR_IN  P3DIR|=BIT1  //端口输出模式
#define ADS_DIN_1   P3OUT|=BIT1  //命令写入AD
#define ADS_DIN_0   P3OUT&=~BIT1
#define ADS_DIR_OT  P2DIR&=~BIT0 //端口为输入模式
#define ADS_CLK_DIR P4DIR|=BIT4  //端口为输出模式
#define ADS_CLK_1   P4OUT|=BIT4  //时钟置1
#define ADS_CLK_0   P4OUT&=~BIT4 //时钟置0
#define DIR_BUSY    P4DIR&=~BIT0
//#define DATA_IN     ((P4IN>>2 & 0x01)
#define DATA_IN     (P2IN & 0x01)
#define BUSY_IN     (P4IN & 0x01) //读输入数据
void Check_busy(void);
void SPI_WR(uchar DATA);
void Init_Port(void);
void delay(uint temp);
uint ADS7841_Read_Data(uchar Channel);
uint temp_DATA[100];
void delay(uint temp1)
{
  int i;
  for(i=temp1;i>0;i--)
  {
    ;
  }
}
uint ADS7841_Read_Data(uchar Channel)  //Channel=0:CH0;1:CH1;2:CH2;3:CH3;
{
  uint ADCResult=0;
  uchar i,ADS_CHANNEL;
  uint TempBit =0;
  uchar COMMAND=0;
  switch (Channel)
  {
     case 0:ADS_CHANNEL=0x10;break; //通道选择
     case 1:ADS_CHANNEL=0x50;break;
     case 2:ADS_CHANNEL=0x20;break;
     case 3:ADS_CHANNEL=0x60;break;
     default:ADS_CHANNEL=0x10;break;       
  }
  COMMAND=(ADS_S|ADS_CHANNEL|ADS_S_D|ADS_POWER);
  ADS_CLK_0;
  ADS_DIN_0;     ///DIN先置0
  ADS_CS_0;  //;片选信号
  //SPI_WR(COMMAND);                //SPI总线写命令子程序
  //ADS_DIR_IN;              //端口定义为输出模式,上升沿发送,下降沿接受
  for(i=0;i<8;i++)
  { 
     ADS_CLK_1;
     if( (COMMAND & 0x80) ==0x80)
     {
        ADS_DIN_1;        //写入指令
     }
     else
     {
        ADS_DIN_0;
     }
     COMMAND<<=1;                   //左移
     delay(5);
     ADS_CLK_0;
     delay(5);                  //模拟SPI串行接口 发送数据                    
  }
  delay(5);
  ADS_CLK_0;
  Check_busy();
  //delay(5);
  for(i=0;i<12;i++)
  {                              //上升沿读出数据   
     ADS_CLK_0;
     delay(4);
    if( DATA_IN==0x01 )
     {
       TempBit=1;
     }
     else
     {
       TempBit=0;
     }
    ADS_CLK_1;
    ADCResult=((ADCResult<<1)|TempBit);    //模拟SPI串行接口,接收数据
    delay(5);
  }
    ADS_CLK_0;
  for(i=0;i<4;i++)
  {
     ADS_CLK_1;
     delay(5);
     ADS_CLK_0;
     delay(5);
  }
  ADS_CS_1;                      //屏蔽片选
  return ADCResult;
}
void Check_busy(void)
{
  int temp;
  //DIR_BUSY;                     //端口设置为输入方式
  ADS_CLK_1;
  temp=BUSY_IN;
  ADS_CLK_0;
  while( (temp&0x01)==0)   //检测到高电平就开始读数。。不然会丢一位
  {
    ADS_CLK_1;              //读端口状态....
    temp=BUSY_IN;
    //delay(5);                 //
    ADS_CLK_0;
  }
  //
 /* do
  {
      ADS_CLK_0;               //读端口状态....
      temp=BUSY_IN;
      delay(5);                 //
      ADS_CLK_1;
  }while((temp&0x01)!=0);      //高位为1为忙信号*/
}
 void SPI_WR(uchar DATA)
{
  uint i;
  ADS_DIR_IN;              //端口定义为输出模式,上升沿发送,下降沿接受
  for(i=0;i<8;i++)
  { 
     ADS_CLK_1;
     if( (DATA & 0x80) ==0x80)
     {
        ADS_DIN_1;        //写入指令
     }
     else
     {
        ADS_DIN_0;
     }
     DATA<<=1;                   //左移
     ADS_CLK_0;
     delay(5);                  //模拟SPI串行接口 发送数据                    
  }
  delay(5);
  ADS_CLK_0;
}
void Init_Port(void)
{
  P3SEL=0X00;
  P4SEL=0X00;
  ADS_DIR_IN;
  ADS_DIR_OT;
  ADS_CLK_DIR;
  DIR_BUSY;
  DIR_CS;
  ADS_CLK_0;
  //delay(5);
  ADS_CS_1;
 // ADS_CLK_1; 
}
void main(void)
{
  WDTCTL = WDTPW+WDTHOLD; //关看门狗
  Init_Port();            //端口初始化
  uint flag=0;
  uint i;
  while(1)
  {
    for(i=0;i<5;i++)
    {
      temp_DATA[i]=ADS7841_Read_Data(0);
      delay(10);
    }
    flag=1;
  }
 
}

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
实时控制.安全.如何加速实现未来工厂落地?