用keil编写c语言代码使stc12c5a60s2单片机控制AD5933芯片校准,AD5933的scl引脚接STC单片机的P1.5引脚,AD5933的sda引脚接STC单片机的P1.6引脚,反馈电阻为10k欧,校准电阻为10k欧
时间: 2023-07-16 17:12:01 浏览: 195
下面是一份基本的代码框架,可以根据具体需要进行修改:
```c
#include <STC12C5A60S2.h>
// 定义AD5933地址
#define ADDR_WRITE 0xD0
#define ADDR_READ 0xD1
// 定义AD5933命令
#define CMD_CONTROL_HB 0x80
#define CMD_CONTROL_LB 0x82
#define CMD_START_FREQ 0x85
#define CMD_FREQ_INC 0x86
#define CMD_FREQ_NUM 0x87
#define CMD_MEASURE 0x88
#define CMD_TEMP_MEAS 0x8F
// 定义校准电阻和反馈电阻
#define CALIB_RESISTOR 10000
#define FEEDBACK_RESISTOR 10000
// 定义变量
unsigned int freqStart = 100; // 起始频率100Hz
unsigned int freqInc = 100; // 频率步进100Hz
unsigned int freqNum = 10; // 频率点数10个
// 函数声明
void delay(unsigned int t);
void i2c_start(void);
void i2c_stop(void);
void i2c_send_byte(unsigned char dat);
unsigned char i2c_recv_byte(void);
void ad5933_init(void);
void ad5933_start_freq_sweep(void);
// 主函数
void main(void)
{
// 初始化IO口
P1M1 = 0x00; //P1.5和P1.6设置为普通IO口
P1M0 = 0xFF;
// 初始化AD5933
ad5933_init();
// 启动频率扫描
ad5933_start_freq_sweep();
while(1);
}
// 延时函数
void delay(unsigned int t)
{
unsigned int i;
while(t--)
for(i=0; i<100; i++);
}
// I2C总线起始信号
void i2c_start(void)
{
SDA = 1;
SCL = 1;
delay(1);
SDA = 0;
delay(1);
SCL = 0;
delay(1);
}
// I2C总线停止信号
void i2c_stop(void)
{
SDA = 0;
SCL = 1;
delay(1);
SDA = 1;
delay(1);
}
// I2C总线发送一个字节
void i2c_send_byte(unsigned char dat)
{
unsigned char i;
for(i=0; i<8; i++)
{
SDA = (dat & 0x80) ? 1 : 0;
SCL = 1;
delay(1);
SCL = 0;
dat <<= 1;
delay(1);
}
SDA = 1; // 主机释放SDA总线
SCL = 1; // 主机读取ACK位
delay(1);
SCL = 0; // 主机发送P时钟结束
delay(1);
}
// I2C总线接收一个字节
unsigned char i2c_recv_byte(void)
{
unsigned char i, dat = 0;
SDA = 1; // 主机释放SDA总线
for(i=0; i<8; i++)
{
SCL = 1;
delay(1);
dat <<= 1;
dat |= SDA;
SCL = 0;
delay(1);
}
return dat;
}
// 初始化AD5933
void ad5933_init(void)
{
// 控制字节1: 外部时钟源,增量模式,输出振幅2Vpp
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_CONTROL_HB);
i2c_send_byte(0x10);
i2c_stop();
// 控制字节2: 内部系统时钟,增量模式,1个增量,输出振幅2Vpp
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_CONTROL_LB);
i2c_send_byte(0x01);
i2c_stop();
// 设置起始频率
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_START_FREQ);
i2c_send_byte((unsigned char)(freqStart >> 8));
i2c_send_byte((unsigned char)freqStart);
i2c_stop();
// 设置频率步进
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_FREQ_INC);
i2c_send_byte((unsigned char)(freqInc >> 8));
i2c_send_byte((unsigned char)freqInc);
i2c_stop();
// 设置频率点数
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_FREQ_NUM);
i2c_send_byte((unsigned char)(freqNum >> 8));
i2c_send_byte((unsigned char)freqNum);
i2c_stop();
// 设置增益
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_MEASURE);
i2c_send_byte(0x01);
i2c_stop();
}
// 启动频率扫描
void ad5933_start_freq_sweep(void)
{
unsigned int i;
unsigned long real = 0; // 实部
unsigned long image = 0; // 虚部
unsigned long impedance = 0; // 阻抗值
unsigned long resistance = 0; // 校准电阻值
float gain = 0, phase = 0; // 增益和相位
for(i=0; i<freqNum; i++)
{
// 发送测量命令
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_MEASURE);
i2c_send_byte(0x01);
i2c_stop();
// 等待测量完成
while(1)
{
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_MEASURE);
if(i2c_recv_byte() & 0x01)
break;
i2c_stop();
}
i2c_stop();
// 读取实部和虚部
i2c_start();
i2c_send_byte(ADDR_WRITE);
i2c_send_byte(CMD_TEMP_MEAS);
i2c_stop();
i2c_start();
i2c_send_byte(ADDR_READ);
real = i2c_recv_byte();
real <<= 8;
real |= i2c_recv_byte();
image = i2c_recv_byte();
image <<= 8;
image |= i2c_recv_byte();
i2c_stop();
// 计算阻抗值
impedance = (real * real) + (image * image);
impedance = (unsigned long)sqrt((float)impedance);
// 计算校准电阻值
resistance = impedance / gain;
// 输出校准电阻值
printf("Resistance: %ld\r\n", resistance);
// 更新增益和相位
gain = (float)CALIB_RESISTOR / (float)resistance;
phase = atan2((float)image, (float)real) * 180.0 / 3.1415926;
}
}
```
需要注意的是,以上代码仅供参考,具体实现可能需要根据硬件电路和AD5933数据手册进行调整。另外,需要注意STC12C5A60S2单片机的I2C时序和AD5933的I2C时序是否一致,如果不一致需要进行相应调整。
阅读全文