模拟spi总线操作ad转换芯片cs1180,实现电压、电流表,以下为CODE
cs1180.c-模式转换芯片驱动
/******************************************
*MCU:stc15wk32s4
*AUTHOR:Golf
******************************************/
#include <stdio.h>
#include "CS1180.h"
#include "Usart_Init.h"
//寄存器地址定义
#define SETUP 0X00//PGA 及BO//cs 控制
#define MUX 0X01//输入通道选择
#define ACR 0X02//模拟电路控制
#define ODAC 0X03//Offset DAC 设置
#define DIO 0X04//数字I/O 引脚设置
#define DIR 0X05//输入输出的方向选择
#define IOCON 0X06//I/O 配置寄存器
#define OCC0 0X07//失调误差正系数
#define OCC1 0X08//失调误差正系数
#define OCC2 0X09//失调误差正系数
#define GCC0 0X0A//增益误差校正系数
#define GCC1 0X0B//增益误差校正系数
#define GCC2 0X0C//增益误差校正系数
#define DOR2 0X0D//模数转换数据高8位
#define DOR1 0X0E//模数转换数据中8位
#define DOR0 0X0F//模数转换数据低8位
//命令定义
#define RDATA 0X01//从DOR 寄存器中读取数据
#define RDATAC 0X03//从DOR 寄存器中连续读取数据
#define STOPC 0X0F//停止从DOR 寄存器中连续读取数据
#define RREG 0X10//低4位为寄存器地址
#define WREG 0X50//低4位为寄存器地址
#define CALSELF 0XF0//对芯片的失调误差和增益误差进行纠正
#define OCALSELF 0XF1//对芯片的失调误差进行纠正
#define GCALSELF 0XF2//对芯片的增益误差进行纠正
#define OCALSYS 0XF3//对系统的失调误差进行纠正
#define GCALSYS 0XF4//对系统的增益误差进行纠正
#define WAKEUP 0XFB//将系统从睡眠模式模式中唤醒
#define SYNC 0XFC//对DRDY 进行同步
#define SLEEP 0XFD//使芯片进入睡眠模式
#define RESET 0XFE//将芯片复位到上电后的状态
#define P_ADD 0XA3//将芯片复位到上电后的状态
//IO口定义
#define DRDY2 P32
#define DRDY1 P33
#define SCK P34
#define SDO P35
#define SDI P36
#define CS1_A P37
#define CS2_V P20
xdata adi ad_d[2];
bit ad_a_ok,ad_v_ok;//ADC转换完标志
/*写一个字节的数据到CS1180的SDI引脚*/
void Write_One_Byte(unsigned char Byte)
{
char i=0;
for(;i<8;i++)
{
SDI = (bit)(Byte&(0x80>>i)); //先传高位
SCK = 0; //写数据的时候,数据在上升沿被写入
SCK = 1;
}
}
/*从SDO引脚读取一个字节的数据*/
unsigned char Read_One_Byte(void)
{
char i=0;
unsigned char Data = 0;
for(;i<8;i++)
{
SCK = 1; //读数据的时候,数据在下降沿被输出
SCK = 0;
Data = (Data << 1) | SDO;
}
SCK = 1;
return Data;
}
/*1:读取ADC数据 命令编码:0x01*/
unsigned long Read_Adc_Data(void)
{
char datah;
unsigned char datam,datal;
signed long c=0;
datal=datam=datah=0;
Write_One_Byte(0x01); //写入命令:0x01 写完后SCK=1
datah=Read_One_Byte();
datam=Read_One_Byte();
datal=Read_One_Byte();
c=datah<<16|datam<<8|datal;
return(c);
}
/*2:读取寄存器的值 命令编码:0001 rrrr xxxx nnnn*/
void Read_Reg_Data(char start_reg_addr,char num,char *ptr)
{
Write_One_Byte(0x10|start_reg_addr); //命令的第一个字节
Write_One_Byte(num-1);
for(;num!=0;num--)
{
*(ptr++) = Read_One_Byte(); //将读取的寄存器的值顺序保存在数组中
}
}
/*3:写数据到控制寄存器中 命令编码:0101 rrrr xxxx nnnn*/
unsigned char Write_Reg_Data(char start_reg_addr,char reg_data)
{
char err_num = 0;
Write_One_Byte(0x50|start_reg_addr); //命令的第一个字节,第一个寄存器为0x00
Write_One_Byte(0x00); //命令的第二个字节,总共写1个寄存器
Write_One_Byte(reg_data); //写入第一个寄存器值
return 0;
}
//4:CS1180初始化函数
void CS1180_ADC_Init(void)
{
//全部为准双向口
P3M0=0;
P3M1=0;
P2M0&=~0x01;
P2M1&=~0x01;
//初始化电流ADC
CS1_A = 0;
Write_One_Byte(RESET);
Write_Reg_Data(SETUP,0x02);
Write_Reg_Data(ACR,0x62);
Write_Reg_Data(ODAC,0x30);
CS1_A = 1;
//初始化电压ADC
CS2_V = 0;
Write_One_Byte(RESET);
Write_Reg_Data(ACR,0x62);
Write_Reg_Data(ODAC,0x30);
CS2_V = 1;
//外部中断初始化
IT0=1;//下降沿触发
EX0=1;//开中断
IT1=1;//下降沿触发
EX1=1;//开中断
}
/*外部中断0响应函数 读取电压*/
void Int0_func() interrupt 0
{
EX1 = 0; //关掉电流表中断
if(DRDY2==0)
{
LED1 = 0;
CS2_V = 0;
ad_d[1].ad_re = Read_Adc_Data();
CS2_V = 1;
IE0 = 0; //外部中断标志位清0
ad_a_ok = 1;
LED1 = 1;
}
EX1=1;
}
/*外部中断1响应函数 读取电流*/
void Int1_func() interrupt 2
{
EX0 = 0; //关掉电压表中断
if(DRDY1==0)
{
LED2 = 0;
CS1_A = 0;
ad_d[0].ad_re = Read_Adc_Data();
CS1_A = 1;
IE1 = 0; //外部中断标志位清0
ad_v_ok = 1;
LED2 = 1;
}
EX0 = 1;
}