| 
				打卡等级:初来乍到打卡总天数:7最近打卡:2025-08-18 12:23:08  已绑定手机注册会员 
 
 
	积分127 
 | 
 
| 大佬们好,我接触单片机一小段时间,但苦于身边没有人可以请教,特此发帖。 
 
 本人使用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
 
 
 
 | 
 |