c8051f020 ADS1248

2020-01-20 19:06发布

/********************************************************************************************
第一次编写SPI接口的芯片,编写了三天,最后还是在淘宝上要的资料才编出的,哎,
该代码是用c8051f020的I/Om模拟的SPI ,自己没有变出来的原因(1)文档没仔细看,
对读写寄存器那块的操作没看懂,没注意到 读写寄存器那块上面的指令

编写者:漠北的孤狼

编写地点;本部飞思卡尔实验室

编写时间 2013 8 20

代码首次完成时间 2013 8 20 9点24分

********************************************************************************************/

#include<c8051f020.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char                                                                                                        

unsigned long  results=0;
unsigned char  AD_reg[6];
unsigned char char_results[3];
unsigned int DELAY_10ms = 10000;
unsigned char red_Adc = 0;

//*********************************指令集****************************************************
#define   ADS1248_CMD_WAKEUP    0x00          // Exit sleep mode
#define   ADS1248_CMD_SLEEP     0x02          // Enter sleep mode
#define   ADS1248_CMD_SYNC      0x04          // Synchronize the A/D conversion
#define   ADS1248_CMD_RESET     0x06          //  Reset to power-up values
#define   ADS1248_CMD_NOP       0xff          //  No operation
#define   ADS1248_CMD_RDATA     0x12          //  Read data once
#define   ADS1248_CMD_RDATAC    0x14          //  Read data continuously
#define   ADS1248_CMD_SDATAC    0x16          //  Stop reading data continuously
#define   ADS1248_CMD_RREG      0x20          //  Read from register rrrr
#define   ADS1248_CMD_WREG      0x40      //  Write to register rrrr
#define          ADS1248_CMD_SYSOCAL        0x60      //  System offset calibration
#define          ADS1248_CMD_SYSGCAL        0x61          //  System gain calibration
#define          ADS1248_CMD_SELFOCAL        0x62           //        Self offset calibration               
//*********************************寄存器集*****************************************************
#define   ADS1248_REG_MUX0    0x00
#define   ADS1248_REG_VBIAS   0x01
#define   ADS1248_REG_MUX1    0x02
#define   ADS1248_REG_SYS0    0x03
#define   ADS1248_REG_CFC0    0x04
#define   ADS1248_REG_CFC1    0x05
#define   ADS1248_REG_CFC2    0x06
#define   ADS1248_REG_FSC0    0x07
#define   ADS1248_REG_FSC1    0x08
#define   ADS1248_REG_FSC2    0x09
#define   ADS1248_REG_IDAC0   0x0a
#define   ADS1248_REG_IDAC1   0x0b
#define   ADS1248_REG_GPIOCFG  0x0c
#define   ADS1248_REG_GPIODIR  0x0d
#define   ADS1248_REG_GPIODAT  0x0e
////***********************SPI引脚 ********************************          
sbit TX0 = P0^0;             //C8051F0200中串口引脚
sbit RT0 = P0^1;            //C8051F0200中窜口引脚
sbit ADS_SCLK= P0^4;        //结C8051f020的SCK          时钟
sbit ADS_Din = P0^5;        //结C8051f020的MISO           数据输入
sbit ADS_Dout = P0^6;        //结C8051f020的MOSI, 数据输出端
sbit ADS_CS =  P3^0;            //结C8051f020的NSS,片选,此程序中未用,直接接低电平了
sbit ADS_DRDY = P0^2;  //程序中此端口接P3.2,用于外部中断  =P0^6;
sbit ADS_Start =P0^7;           //转换启动                                                                                          
sbit ADS_RESET = P0^3;                 //复位
///************************************************************************************/
//=====================================SPI的接口定义=========================================
/***********************************************************************************
* 函数名称:Delay;
*
* 函数功能描述:延时n微秒子函数;
*              
* 输入参数:延时时间(单位微秒);
*
* 返回数据:none;
*
* 注意:    none;
************************************************************************************/
void Delay(unsigned char Times)
{
    unsigned char i;
        for (i=0; i<Times; i++)
        {
                _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
                _nop_();_nop_();_nop_();_nop_();
                _nop_();
        }
}  
//*************************c8051f020模块中的函数 开始***********************************************
//======================================================================================
//外部晶振初始化函数
void Oscillator_init(void)                                  
{
    int i = 0;
    OSCXCN    = 0x67;
    for (i = 0; i < 3000; i++);  // Wait 1ms for initialization
    while ((OSCXCN & 0x80) == 0);
    OSCICN    = 0x0C;
}
//======================================================================================
//关看门狗函数
void Reset_sources_init(void)                          
{
    WDTCN     = 0xDE;
    WDTCN     = 0xAD;
}
//======================================================================================
//IO初始化函数
void Port_iO_init(void)               
{                                                 

        XBR0      = 0x04;                          //串口TX0是P0^0,RT0是P0^1,SCK是P0^4,MISO是P0^5,MOSI是P0^6
    XBR1      = 0x04;
    XBR2      = 0xC0;
    P0MDOUT   |= 0xff;                      //把P0^0到P0^5设置为推挽输出
}

void Interrupts_Init(void)
{
    IE        |= 0x81;
        IE        |= 0x10;                  //串口中断
       
}

//======================================================================================
//串口初始化函数
void UART0_init(void)  //串口0初始化
{
        SCON0=0x50;            //串口方式1
        TMOD=0X20;             //选用定时器1作为波特率发生器
        TH1=(65536-600)/256;              
        TL1=(65536-600)%256;
        PCON=0x80;                                //波特率为9600
        TR1=1;                       //定时器启动
}
//======================================================================================
//c8051f020的SPI模式设置函数
void SPI_init(void)                          
{
//        SPI0CN    |= 0x01;                          //启动SPI
//        SPI0CN    |= 0x03;                          //SPI工作方式为主机模式,系统默认的是从机模式
//        SPI0CFG   |= 0x80;                      //SPI时钟相位在第二个SCK周期采样,系统默认的是在第一个SCK周期采样
//        SPI0CFG   |= 0x40;                      //SPI时钟极性为空闲高电平,系统默认的是空闲为低电平
}


/** Send a char to MC **/

void sendChar(unsigned char ch)
{
        SBUF0 = ch;
        while(TI0 == 0);
        TI0 = 0;
}
//*******************************串口模块化程序 结束********************************************************

//*******************************SPI构架的第一层 开始************************************************************
//*******************************SPI构架的第一层 开始************************************************************
//-----------------------------------------------------------------//
//        功    能:延时
//        入口参数: 延时时间 delay * us
//        出口参数: /
//        全局变量: /
//        备    注:
//-----------------------------------------------------------------//

//*************************************模拟 SPI程序**************************************************
//-----------------------------------------------------------------//
//        功    能:IO口模拟的SPI程序,ADS1248 SPI接口程序
//        入口参数: /
//        出口参数: /
//        全局变量: /
//        备    注: SPI速度最高2MHz,用于命令发送等操作
//-----------------------------------------------------------------//
unsigned char ADS1248SPI(unsigned char m)
{
    //SPI速度最高2MHz,用于命令发送等操作
    unsigned char i,r=0;
    for(i=0;i<8;i++)
    {
      ADS_SCLK = 1;
      r=r<<1;

      if(m & 0x80)                                                        //
          {
                   ADS_Din = 1;
          }          
          else
          {  
                  ADS_Din = 0;
          }
          m = m<<1;

      ADS_SCLK = 0;
      if(ADS_Dout == 1)
          {
                  r++;
          }
    }
    return r;
}

//-----------------------------------------------------------------//
//        功    能:ADS1248 读取
//        入口参数: /
//        出口参数: /
//        全局变量: /
//        备    注:
//        SPI速度最高2MHz,用于读取AD的24位结果.在使用START引脚控制ADS1248时,可使用此函数
//        输出为有符号数。已经把ADS1248的输出格式转变为有符号数,0输入对应码值0,正最大对应7FFFFF,负最大对应-7FFFFF
//        WriteOut是在发送24个SCLK以读取数据的同时写出去的24位指令,比如写入MUX0寄存器以改变通道。注意此次读取的为设置改变前的结果
//        如果WriteOut是操作控制寄存器,则START线应该保持高
//-----------------------------------------------------------------//

unsigned long ADS1248ReadData(unsigned long WriteOut)
{
    unsigned char i=0;
    unsigned long r=0;
    for(i=0;i<24;i++)
    {
      ADS_SCLK = 1;
      r=r<<1;
          Delay(10);

      if (WriteOut & 0x800000)
          {
                  ADS_Din = 1;
          }
          else
          {
                  ADS_Din = 0;
          }
          WriteOut=WriteOut<<1;

      ADS_SCLK = 0;
      if(ADS_Dout)
          {
                  r++;
          }
    }                 
    return r;
}
//*******************************SPI构架的第一层 结束************************************************************
//*******************************SPI构架的第一层 结束************************************************************
//===============================================================================================================
//*******************************SPI构架的第二层 开始************************************************************
//*******************************SPI构架的第二层 开始************************************************************
//-----------------------------------------------------------------//
//        功    能:ADS1248 写寄存器
//        入口参数: /
//        出口参数: /
//        全局变量: /
//        备    注: 向ADS1248中地址为regaddr的寄存器写入一个字节databyte
//-----------------------------------------------------------------//

void ADS1248WREG(unsigned char regaddr,unsigned char databyte)                   //直接看文档53页写寄存器3个指令就可以了
{
                                                               
    ADS1248SPI(ADS1248_CMD_WREG+(regaddr & 0xF));                                //向寄存器写入数据地址,为什么&0xf?因为是16位的寄存器
    ADS1248SPI(0);                                                                                                //写入数据的个数n-1
    ADS1248SPI(databyte);                                                                                //向regaddr地址指向的寄存器写入数据databyte
}

//-----------------------------------------------------------------//
//        功    能:ADS1248 读寄存器
//        入口参数: /
//        出口参数: /
//        全局变量: /
//        备    注: 从ADS1248中地址为regaddr的寄存器读出一个字节databyte
//-----------------------------------------------------------------//

unsigned char ADS1248RREG(unsigned char regaddr)
{                                                                                                                                  // 看文档53页读寄存器的指令
                                             
    unsigned char r=0;                                                                                        //从ADS1248中地址为regaddr的寄存器读出一个字节
                                                                                                                            //在ADS1248_CMD_RREG的基础上加regaddr & 0xF)
    ADS1248SPI(ADS1248_CMD_RREG+(regaddr & 0xF));                                //写入地址,为什么是&0xf,因为是16位的寄存器
    ADS1248SPI(0);                                                                                                //写入读取数据的个数n-1
    r=ADS1248SPI(ADS1248_CMD_NOP);                                                                //读出regaddr地址指向的寄存器的数据,这是明智的
    return r;//返回数据
}
//*******************************SPI构架的第二层 结束************************************************************
//*******************************SPI构架的第二层 结束************************************************************
//===============================================================================================================
//*******************************SPI构架的第三层 开始************************************************************
//*******************************SPI构架的第三层 开始************************************************************

//连续的读,连续的写

//*******************************SPI构架的第三层 结束************************************************************
//*******************************SPI构架的第三层 结束************************************************************


//*******************************ADS1248的AD模块的函数 ************************************************************
void Ads1248(void)
{                                             
    ADS1248SPI(ADS1248_CMD_RDATA);                        //发送单次读数据命令
    results=ADS1248ReadData(0xFFFFFF);                //读取ADC转换完成的数据,24位数故6个F,当然了还可以是7FFFFFF,000000,
                                                //等不同地点模式,差别是单端输入的值得范围不同,见文档35页详解
    ADS1248SPI(ADS1248_CMD_NOP);                        //发送空操作指令,强迫D_OUT变高
}
//*******************************SPI构架的第四层 开始************************************************************
//*******************************SPI构架的第四层 开始************************************************************

//-----------------------------------------------------------------//
//        功    能:ADS1248初始化子程序
//        入口参数: /
//        出口参数: /
//        全局变量: /
//        备    注: /
//-----------------------------------------------------------------//
void InitADS1248(void)
{
    Delay(10);
          
    ADS_Start = 0;
        ADS_CS = 0;

        //发送复位命令
    ADS_RESET = 0;
    Delay(DELAY_10ms);
    ADS_RESET = 1;

                                                                                //在写寄存器的函数中给寄存器的地址以及它的指令
    //ADS1248SPI(ADS1248_CMD_RESET);
    //初始化MUX0多路复用控制寄存器
    ADS1248WREG(ADS1248_REG_MUX0,0x07); //00100101,Bit7-6:传感器电流源检测不使用,Bit5-3:正输入为AIN0,Bit2-0:负输入为AIN1 ,通道的选择 (0x00)是单通道0
    //初始化MUX1多路复用控制寄存器
    ADS1248WREG(ADS1248_REG_MUX1,0x33); //00110000,Bit7:启用内部晶振,Bit6-5:内部基准一直打开,Bit4-3:输入基准为片上基准,Bit2-0:普通模式
    //延时等待10ms,等待内部基准稳定,可以打内部传感器         ADS1248WREG(ADS1248_REG_MUX1,0x03)打开内部温度传感器
    Delay(6*DELAY_10ms);
    //初始化VBIAS偏压寄存器
    ADS1248WREG(ADS1248_REG_VBIAS,0); //00000000,Bit7-0:偏置电压选择关闭(默认)
    //初始化IDAC1控制寄存器
    ADS1248WREG(ADS1248_REG_IDAC1,0xFF);//11111111,Bit7-4:断开内部第一恒流源的连接,Bit3-0:断开内部第二恒流源的连接  0X8F打开第一内部恒流源
    //初始化IDAC0控制寄存器
    ADS1248WREG(ADS1248_REG_IDAC0,0x00); //00001000,Bit7-4:只读,Bit3:DRDY/DOUT功能复用Dout线 ,Bit2-0:关闭内部恒流源
    //初始化SYS0系统控制寄存器
    ADS1248WREG(ADS1248_REG_SYS0,0x09); //00000000,Bit7:必须设置为0,Bit6-41:选择1倍增益,Bit3-0:选择2000SPS测量速度
}
//************************************主函数模块开始****************************************************
void main(void)
{   
    unsigned long fVoltage;
        unsigned char buf[10],i;
   
        unsigned long Result_sum=0;
        Result_sum = 0;

         ADS_CS = 0;

    Oscillator_init();
        Reset_sources_init();
        Port_iO_init();
        UART0_init();
        Interrupts_Init()
        InitADS1248();

       EA=1;                                 //打开中断         void SYSCLK_Init(void)
           IT0=1;                                 //打开外部中断0边沿触发。IT0=0时是低电平触发。
           EX0=1;                                 //初始化外部中断标志位

    ADS_Start = 0;
        while(1)
        {
                ADS_Start = 1;               //测试单独触发模式 Start为高至少3mS
                Delay(10);                                     //测试结果:每触发一次,发送一次数据。
                ADS_Start = 0;
                Result_sum =  results >> 8;
                if(Result_sum<0x8000)        //测得电压值为正的情况
                {
                   fVoltage=Result_sum*625;  //625=2.048/32768*10000000   6.144位基准电压 32768为2的15次方 10000000为为了计算的准确性转换为整形计算
                   buf[0]=(unsigned char)(fVoltage/10000000);
                   buf[0]=buf[0]+0x30;
                   buf[1]='.';
                   buf[2]=(unsigned char)((fVoltage%10000000)/1000000);
                   buf[2]=buf[2]+0x30;
                   buf[3]=(unsigned char)((fVoltage%1000000)/100000);
                   buf[3]=buf[3]+0x30;
                   buf[4]=(unsigned char)(fVoltage%100000/10000);
                   buf[4]=buf[4]+0x30;
                   buf[5]=(unsigned char)(fVoltage%10000/1000);
                   buf[5]=buf[5]+0x30;
                   buf[6]=(unsigned char)(fVoltage%1000/100);
                   buf[6]=buf[6]+0x30;        
                   buf[7]='V';                             //V
                   buf[8]=0x20;
                   buf[9]=0x20;
                 }
                 else                                             //测得电压值为负的情况
                 {
                   //buf[0]='-';                                               //取‘-’号
                   Result_sum=0xffff-Result_sum;           //取反运算
                   fVoltage=Result_sum*625;  //625=2.048/32768*10000000   6.144位基准电压 32768为2的15次方 10000000为为了计算的准确性转换为整形计算
                   buf[0]=(unsigned char)(fVoltage/10000000);
                   buf[0]=buf[0]+0x30;
                   buf[1]='.';
                   buf[2]=(unsigned char)((fVoltage%10000000)/1000000);
                   buf[2]=buf[2]+0x30;
                   buf[3]=(unsigned char)((fVoltage%1000000)/100000);
                   buf[3]=buf[3]+0x30;
                   buf[4]=(unsigned char)(fVoltage%100000/10000);
                   buf[4]=buf[4]+0x30;
                   buf[5]=(unsigned char)(fVoltage%10000/1000);
                   buf[5]=buf[5]+0x30;
                   buf[6]=(unsigned char)(fVoltage%1000/100);
                   buf[6]=buf[6]+0x30;        
                   buf[7]='V';                        //V         
                   buf[8]=0x20;                        //空格
                   buf[9]='-';
                 }
               
                   i=0;
                   while(i<10)
                   {
                         sendChar(buf[i]);
                         i++;
                   }
  
           Delay(5*DELAY_10ms);                   //延时
/***************************************************************/
   }
}

//*******************************SPI构架的第四层 结束************************************************************
//*******************************SPI构架的第四层 结束************************************************************
/** COM receive message interrupt function**/

void inteReceive (void) interrupt 4
{
        if(RI0 == 1)
        {
                RI0 = 0;
        }
}
void ISR_ADC_DRDY(void) interrupt 0
{
        EX0=0;         //外部中断0关                       
        Ads1248();           //读取AD值,读取的数值存储在全局变量中。

        sendChar((unsigned long)(results >> 16) & 0x0000ff); //发送最高位       
        sendChar((unsigned long)(results >> 8) & 0x0000ff);         //发送中间位
    sendChar((unsigned long)results & 0x0000ff);                 //发送低位
    EX0 = 1;         
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
陈远鹏
1楼-- · 2020-01-20 20:21
刚写了一个ADS1248的程序,想和大家交流一下
tuowai
2楼-- · 2020-01-21 01:42
 精彩回答 2  元偷偷看……
wkman
3楼-- · 2020-01-21 03:09
备注下,以后可能用到!谢谢分享!
永恒520
4楼-- · 2020-01-21 07:05
楼主写的很不错…谢谢分享
电子学生
5楼-- · 2020-01-21 08:52
谢谢 分享!!
机器人天空
6楼-- · 2020-01-21 12:57
不错,学习了

一周热门 更多>