- 打卡等级:初来乍到
- 打卡总天数:5
- 最近打卡:2025-08-13 11:24:48
已绑定手机
注册会员
- 积分
- 51
|
大佬们好,我接触单片机一小段时间,但苦于身边没有人可以请教,特此发帖。
本人使用ai801u做一个项目,内容是通过硬件i2c沟通外部adc采集电压信号,并最终将数据通过usb传入pc端。结果是可以采集到一些电压信号,换算过来也是正确的,但是部分电压信号采集不到。不清楚是什么原因,个人猜测是不是中断函数优先级需要额外编写代码,又或者usb协议有什么不通的地方。本人之前用stc89c52做这个项目,但是因为位数不够所以才更换的单片机,但那时候并没有出现过测不到数据的情况。
如果需要实际表现的数据,需要明天去到实验室内上电测试一下。
我使用的是中断模式沟通硬件i2c,usb用的也是官方的库文件去配置,应该同属于中断函数。
我现在的问题在于,我查阅了官网上很多的资料包括官方例程,但是首先跟我类似的做法似乎很少,硬件i2c的例程也是很少;其次i2c协议是使用的开漏输出,但是例程里io口全部都配置为0x00,我也查不到哪里有说硬件i2c跟i2c协议有什么不同。下面贴出我编写的代码,烦请大佬们指正,万分感谢。
主函数部分:
#include "AI8051U.H"
#include "ADC.h"
#include "Delay.h"
#include "stc32_stc8_usb.h"
bit CommandByte;
long Data;
int main (void)
{
EAXFR = 1; //,使能访问XFR
WTST = 0;
CKCON = 0;
P0M1 = 0x00; P0M0 = 0x00;
P1M1 = 0x00; P1M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
P6M1 = 0x00; P6M0 = 0x00;
P7M1 = 0x00; P7M0 = 0x00;
P2M0 = 0x00; P2M1 = 0x00; //引脚23、24作为sda和scl
usb_init();
EA = 1; //使能中断
IE2 |= 0x80; //USB中断使能
I2CMSCR = 0x80; //主机模式I2C中断使能
I2CCFG = 0XDC; //使能I2C主机模式 此处应当是控制速度
I2CPSCR = 0x00; //时钟分频寄存器
I2CMSST = 0x00;
PUSBH = 1;PUSB = 0;
PI2CH = 1;PI2C = 1;
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady)
{
unsigned char IE2_bak; // 保存IE2的临时变量
IE2_bak = IE2; // 保存当前IE2值
IE2 |= 0x80;
if(UsbOutBuffer[0] == 0XAA) //判定触发条件
{
CommandByte = 1;
usb_OUT_done();
}
IE2 = IE2_bak; // 恢复IE2值
}
if(CommandByte)
{
ADC_WriteControl();
Data = ADC_ReadData();
Delay(1);
USB_SendData((unsigned char *) & Data ,sizeof( Data ));
CommandByte = 0;
}
}
}
ADC部分:
#include "IIC.h"
#include "Delay.h"
#define ADC_AddressReceive 0x48
#define ADC_AddressRead 0x49
#define ADC_channel 0xB0
int ADC_WriteControl()
{
IIC_Start();
IIC_SendByte(ADC_AddressReceive);
IIC_ReceiveAck();
IIC_SendByte(ADC_channel);
IIC_ReceiveAck();
return ADC_AddressRead;
}
long ADC_ReadData()
{
long Data = 0;
unsigned char i;
IIC_Start();
IIC_SendByte(ADC_AddressRead);
IIC_ReceiveAck();
for (i = 0;i<3;i++)
{
Data<<=8;
Data |= IIC_ReceiveByte();
if(i<2)
{
IIC_SendAck();
}
else
{
IIC_SendNAk();
}
}
IIC_Stop();
return Data;
}
ADC头文件:
#ifndef __ADC_H__
#define __ADC_H__
int ADC_WriteControl();
long ADC_ReadData();
#endif
硬件iic中断模式:
#include "AI8051U.H"
#include "Delay.h"
sbit IIC_SCL=P2^4;
sbit IIC_SDA=P2^3;
bit busy;
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void IIC_Start()
{
busy = 1;
I2CMSCR = 0x81;
while(busy);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void IIC_Stop()
{
busy = 1;
I2CMSCR = 0x86;
while(busy);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void IIC_SendByte(char Data)
{
I2CTXD = Data;
busy = 1;
I2CMSCR = 0x82;
while(busy);
}
/**
* @brief I2C接收一个字节
* @param 无
* @retval 接收到的一个字节数据
*/
char IIC_ReceiveByte()
{
busy = 1;
I2CMSCR = 0x84;
while(busy);
return I2CRXD;
}
/**
* @brief I2C发送应答
* @param AckBit 应答位,0为应答,1为非应答
* @retval 无
*/
void IIC_SendAck()
{
I2CMSST = 0x00;
busy = 1;
I2CMSCR = 0x85;
while(busy);
}
/**
* @brief I2C接收应答位
* @param 无
* @retval 接收到的应答位,0为应答,1为非应答
*/
void IIC_ReceiveAck()
{
busy = 1;
I2CMSCR = 0x83;
while(busy);
}
void IIC_SendNAk()
{
I2CMSST = 0x01;
busy = 1;
I2CMSCR = 0x85;
while(busy);
}
void I2C_Isr() interrupt 24
{
unsigned char EAXFR_bak; // 保存EAXFR的临时变量
EAXFR_bak = EAXFR; // 保存当前EAXFR值
EAXFR = 1; //修改当前EAXFR值
if(I2CMSST&0x40)
{
I2CMSST &= ~0x40;
busy = 0;
}
EAXFR = EAXFR_bak; // 恢复EAXFR值
}
硬件iic头文件:
#ifndef __IIC_H__
#define __IIC_H__
void IIC_Start();
void IIC_Stop();
void IIC_SendByte(char Data);
char IIC_ReceiveByte();
void IIC_SendAck();
void IIC_ReceiveAck();
void IIC_SendNAk();
void I2C_Isr();
#endif
延迟函数:
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
延迟函数头文件:
#ifndef __Delay_H__
#define __Delay_H__
void Delay(unsigned int xms);
#endif
|
|