www.pudn.com > c8051f020-ADS1248.rar > c8051f020 ADS1248.txt, change:2015-06-29,size:19949b


 
/******************************************************************************************** 
第一次编写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;          
}