/********************************************************************************************
第一次编写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;
}
|
你这个程序能不能正常使用啊