找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3537|回复: 16
打印 上一主题 下一主题
收起左侧

单片机+Proteus仿真I2C设备, 设备无响应, 如何写代码?

[复制链接]
跳转到指定楼层
楼主
如图, 用自带的I2C debugger看, 发送完数据后的状态都是N(nack), 设备无响应
I2C的启动, 发送, 停止都是正常的, 就是设备不响应, 是我代码的问题还是软件的问题?



设备是INA219, 电压电流监测模块

文档给的写数据时序图


文档的典型接法:



我知道一上来就贴代码让人很没有读的欲望, 但我真的排查不出问题,恳请各位帮忙!
51模拟I2C总线的部分
  1. void IIC_ack(){
  2.         uchar i;
  3.         SCLK = 0;                //时钟线置低
  4.         SDA = 1;                //拉高SDA
  5.         delay_us();                //延时, 等待SDA被从机拉低
  6.         SCLK = 1;                //拉高时钟线
  7.         while((SDA == 1) && (i < 255)){
  8.                 i++;                //延时, 继续等待
  9.         }
  10.         SCLK = 0;                //拉低时钟线
  11.         delay_us();
  12. }

  13. void IIC_sentByte(uchar _data){
  14.         uchar i, temp;
  15.         temp = _data;
  16.         for(i = 0; i < 8; i++){
  17.                 temp = temp << 1;        //数据向左移, 左移溢出的一位到PSW寄存器的CY中
  18.                 SCLK = 0;                        //时钟线拉低
  19.                 delay_us();
  20.                 SDA = CY;                        //SDA发送CY中的一位数据
  21.                 SCLK = 1;                        
  22.                 delay_us();        
  23.         }
  24.         SCLK = 0;
  25.         delay_us();
  26.         SDA = 1;                                //释放SDA
  27.         delay_us();

  28. }
复制代码

Proteus仿真时读的代码
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include "IIC_Protocol_for8051.h"
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6.         
  7. //当Slave address为1001010 (4AH)时, A1和A0地址线直接采样SDA上的数据
  8. //即 SDA上跑的数据就是A0, A1获取的数据

  9. void INA219_sent2Reg(uchar regAddress, uint _data){
  10.         uchar data_MSB = _data / 256;  //获取数据高八位
  11.         uchar data_LSB = _data - (data_MSB * 256);                //获取数据低八位
  12.         IIC_init();                                                                  //I2C总线启动
  13.         IIC_start();
  14.         IIC_sentByte(0x94);       //发送Slave address(前7位), 和R/#W位(确认传输方向, 第8位)
  15.                      //0x94 = 0x4A(Slave address) * 2 [在0x4A后加一个R/#W位]
  16.                      //0x94 = 10010100    0x4A = 1001010
  17.         IIC_ack();
  18.         IIC_sentByte(regAddress);                                //发送寄存器地址
  19.         IIC_ack();                                                     //并等待从机是否有Ack(响应)
  20.         IIC_sentByte(data_MSB);                                 //发送数据高8位
  21.         IIC_ack();
  22.         IIC_sentByte(data_LSB);                                 //发送低8位
  23.         IIC_ack();
  24.         IIC_stop();                                                  //I2C总线停止
  25. }
  26. void INA219_init(){
  27.         INA219_sent2Reg(0x05, 0x1000);                    //0x1000是要发送的数据, 无特殊含义
  28. }

  29. void main(){
  30.         INA219_init();
  31.         while(1);
  32. }
复制代码

INA219.pdf (1.31 MB, 下载次数: 6)

我的一些想法:0. 我觉得这个可能是INA219的问题, 因为主机连续发送一个字节后, NACK表示从机没有收到数据, 是不是我的地址写错了
   或者不应该这么写?
1.会不会是这个设备我的接法不正确, 导致其根本就不工作呢?









分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:884307 发表于 2021-2-18 19:13 | 只看该作者
这个注释...我tab按太多了...大家将就看
回复

使用道具 举报

板凳
ID:844772 发表于 2021-2-20 08:54 | 只看该作者
你写的地址是100101,A0,A1应该接在SDA上啊,怎么图上是悬空呢?
回复

使用道具 举报

地板
ID:884307 发表于 2021-2-20 17:50 | 只看该作者
glinfei 发表于 2021-2-20 08:54
你写的地址是100101,A0,A1应该接在SDA上啊,怎么图上是悬空呢?

好像确实应该这样...
不过我把A1,A0和SDA连起来之后这个IC还是无响应nack的状态...
回复

使用道具 举报

5#
ID:155507 发表于 2021-2-22 11:11 | 只看该作者
你的地址写错了


线路接错了




我给你来个程序试试


  1. #include  "reg52.h"
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit K1=P1^0;//设置三个独立键盘
  6. sbit K2=P1^3;
  7. sbit K3=P1^5;
  8. sbit lcdwrite=P2^3;
  9. sbit lcddatecommand=P2^2;
  10. sbit lcde=P2^4;
  11. uchar code secondline[]="00-00-00";
  12. uchar i;
  13. uchar hour,minutes,seconds;
  14. uchar count,num;
  15. uchar cnt;



  16. sbit SCL = P2^0;     //模拟I2C时钟控制位
  17. sbit SDA = P2^1;     //模拟I2C数据传送位

  18. #define ACK 0    //应答标志位
  19. #define NACK 1

  20. void IIC_Start(void);          //启动总线
  21. void IIC_Stop(void);           //结束总线
  22. void IIC_SendACK(bit ACK_Type); //应答子函数
  23. bit IIC_RecvACK_Error(void);
  24. void IIC_SendOneByte(unsigned char TxValue); //字节数据传送函数  
  25. unsigned char IIC_RecvOneByte(void);         //字节数据传送函数  

  26. void Delay_us(unsigned int DelayCycle);  //uS延时函数

  27. #define INA219_RD_Operation 0x81
  28. #define INA219_WR_Operation 0x80

  29. unsigned short INA219_ReadReg(unsigned char RegBase);
  30. bit INA219_WriteReg(unsigned char RegBase, unsigned int RegValue);
  31. void INA219_Init(void);
  32. unsigned int INA219_GetBusVolt(void);
  33. unsigned int INA219_GetPower(void);
  34. unsigned int INA219_GetCurrent(void);

  35. void write_command(uchar command);
  36. void write_date(uchar date);

  37. void Delay_us(unsigned int DelayCycle)
  38. {
  39.         unsigned char i;

  40.         while(DelayCycle--)
  41.         {
  42.                 i = 2;
  43.                 while (--i);
  44.         }
  45. }

  46. void nop4()
  47. {
  48.         _nop_();     //等待一个机器周期
  49.         _nop_();     //等待一个机器周期
  50.         _nop_();     //等待一个机器周期
  51.         _nop_();     //等待一个机器周期
  52. }

  53. //Bus free time between a STOP and START condition: >1.3us
  54. //LOW period of the SCL clock: >1.3us
  55. //HIGH period of the SCL clock: >0.6us
  56. //Set-up time for a repeated START condition: >0.6us
  57. //Hold time (repeated) START condition: >0.6us
  58. //Data set-up time: >0.1us
  59. //Set-up time for STOP condition >0.6us
  60. //Machine Cycle Time = 1.08us @ 11.0592MHz

  61. void IIC_Start(void)
  62. {
  63.         SCL = 1;
  64.         _nop_();
  65.         SDA = 1;
  66.         nop4();
  67.         SDA = 0;
  68.         nop4();
  69.         SCL = 0;
  70.         _nop_();
  71.         _nop_();
  72. }

  73. void IIC_Stop(void)
  74. {
  75.         SDA = 0;
  76.         _nop_();       
  77.         SCL=0;
  78.         nop4();//>4us后SCL跳变
  79.         SCL = 1;
  80.         nop4();
  81.         SDA = 1;
  82.         _nop_();
  83.         _nop_();
  84. }

  85. void IIC_SendACK(bit ACK_Type)
  86. {
  87.         SDA = ACK_Type;
  88.         SCL = 1;
  89.         SCL = 0;
  90.         SDA = 1;                                                        //Release SDA.
  91. }

  92. bit IIC_RecvACK_Error(void)
  93. {
  94.         bit RecvAckError;

  95.         SDA = 1;                                //Write "1" before read.
  96.         SCL = 1;
  97.         RecvAckError = SDA;                //Read SDA.
  98.         SCL = 0;

  99.         return RecvAckError;
  100. }

  101. void IIC_SendOneByte(unsigned char TxValue)
  102. {
  103.         unsigned char i;

  104.         for(i=0; i<8; i++)
  105.         {
  106.                 TxValue <<= 1;                        //Data is transferred with MSB first.
  107.                 SDA = CY;        //If MSB is 1, the Carry Flag (CY) will be set to 1 after left logical shift, and vice versa.
  108.                 _nop_();
  109.                 SCL = 1;
  110.                 nop4();
  111.                 _nop_();   
  112.                 SCL = 0;
  113.         }
  114. }

  115. unsigned char IIC_RecvOneByte(void)
  116. {
  117.         unsigned char RxValue = 0;
  118.         unsigned char i;

  119.         SDA = 1;                                                        //Write "1" before read.
  120.         for(i=0; i<8; i++)
  121.         {
  122.                 _nop_();
  123.                 SCL = 0;
  124.                 nop4();
  125.                 SCL = 1;
  126.                 _nop_();
  127.                 _nop_();
  128.                 RxValue <<= 1;

  129.                 RxValue |= SDA;
  130.                 _nop_();
  131.         }
  132.         SCL = 0;
  133.         _nop_();

  134.         return RxValue;
  135. }


  136. unsigned int INA219_ReadReg(unsigned char RegBase)
  137. {
  138.         unsigned short RegValue = 0;

  139.         IIC_Start();
  140.         IIC_SendOneByte(INA219_WR_Operation);
  141.         if(!IIC_RecvACK_Error())
  142.         {
  143.                 IIC_SendOneByte(RegBase);
  144.                 if(!IIC_RecvACK_Error())
  145.                 {
  146.                         //IIC_Stop();
  147.                         IIC_Start();
  148.                         IIC_SendOneByte(INA219_RD_Operation);
  149.                         if(!IIC_RecvACK_Error())
  150.                         {
  151.                                 RegValue = IIC_RecvOneByte();
  152.                                 IIC_SendACK(ACK);
  153.                                 RegValue = RegValue << 8;
  154.                                 RegValue |= IIC_RecvOneByte();
  155.                                 IIC_SendACK(NACK);
  156.                         }
  157.                 }
  158.         }
  159.         IIC_Stop();

  160.         return RegValue;
  161. }

  162. bit INA219_WriteReg(unsigned char RegBase, unsigned int RegValue)
  163. {
  164.         bit WrRegError = 1;

  165.         IIC_Start();
  166.         IIC_SendOneByte(INA219_WR_Operation);
  167.         if(!IIC_RecvACK_Error())
  168.         {
  169.                 IIC_SendOneByte(RegBase);
  170.                 if(!IIC_RecvACK_Error())
  171.                 {
  172.                         IIC_SendOneByte((RegValue & 0xFF00) >> 8);
  173.                         IIC_RecvACK_Error();
  174.                         IIC_SendOneByte(RegValue & 0x00FF);
  175.                         WrRegError = IIC_RecvACK_Error();
  176.                 }
  177.         }
  178.         IIC_Stop();

  179.         return !WrRegError;
  180. }

  181. void INA219_Init(void)
  182. { //0+
  183.         INA219_WriteReg(0x00, 0x3C1F);//32V FSR, GAIN = 8, 16 samples, Shunt and Bus, Continuous.
  184.         INA219_WriteReg(0x05, 0x1000);//Use INA219 EVM software to calculate a full-scale calibration value (initial calbration), and then compute the corrected full-scale calibration value based on measured current (second calbration).
  185. }

  186. unsigned int INA219_GetBusVolt(void)
  187. {
  188.         unsigned int BusVoltRegVal;
  189.         // Sometimes a sharp load will reset the INA219, which will
  190.         // reset the cal register, meaning CURRENT and POWER will
  191.         // not be available ... avoid this by always setting a cal
  192.         // value even if it's an unfortunate extra step       
  193.         //INA219_WriteReg(0x05, 0x1000);
  194.         BusVoltRegVal = INA219_ReadReg(0x02);
  195.         if(BusVoltRegVal & 0x0001)                                                                //Overflow
  196.         return 0x0FA0;
  197.         else
  198.         return (BusVoltRegVal & 0xFFF8) >> 1;                //((BusVoltRegVal & 0xFFF8) >> 3)*4mV
  199. }

  200. unsigned int INA219_GetPower(void)
  201. {
  202.         unsigned int PowerRegVal;
  203.         //INA219_WriteReg(0x05, 0x1000);
  204.         PowerRegVal = INA219_ReadReg(0x03);
  205.         return (PowerRegVal >> 1)*5;                                                        //2.5mW/bit
  206. }

  207. unsigned int INA219_GetCurrent(void)
  208. {
  209.         unsigned int CurrentRegVal;
  210.         //INA219_WriteReg(0x05, 0x1050);
  211.         CurrentRegVal = INA219_ReadReg(0x04);
  212.         return CurrentRegVal >> 3;                                                                //0.125mA/bit
  213. }


  214. void RefreshData(void)
  215. {
  216.         unsigned int BusVolt, Current, Power;
  217.         unsigned int OffsetCurrent, OffsetPower;
  218.        
  219.         BusVolt = INA219_GetBusVolt();

  220.        
  221.         OffsetCurrent = (BusVolt >> 9) + 2;                        //Gather statistics of the measured current under various voltage conditions when no load is connected to the output port. Use Excel to do curve fitting.
  222.         Current = INA219_GetCurrent();
  223.         if(Current > OffsetCurrent)
  224.         Current -= OffsetCurrent;
  225.         else
  226.         Current = 0;

  227.         write_command(0x80);
  228.         write_date( BusVolt/10000+48);
  229.         write_date( (BusVolt%10000)/1000+48);
  230.         write_date( '.');
  231.         write_date( (BusVolt%1000)/100+48);
  232.         write_date( (BusVolt%100)/10+48);
  233.         write_date( BusVolt%10+48);
  234.         write_date( 'V');
  235.         write_date( ' ');
  236.         write_date( ' ');
  237.        
  238.         write_date(Current/1000+48);
  239.         write_date( '.');
  240.         write_date( (Current%1000)/100+48);
  241.         write_date( (Current%100)/10+48);
  242.         write_date( Current%10+48);
  243.         write_date( 'A');
  244.        
  245.         OffsetPower = ((BusVolt >> 3) * OffsetCurrent)/125 + 6;
  246.         Power = INA219_GetPower();
  247.         if(Power > OffsetPower)
  248.         Power -= OffsetPower;
  249.         else
  250.         Power = 0;
  251.         write_command(0x80+0x49);
  252.         write_date(Power/10000+48);
  253.         write_date((Power%10000)/1000+48);
  254.         write_date( '.');
  255.         write_date((Power%1000)/100+48);
  256.         write_date( (Power%100)/10+48);
  257.         write_date(Power%10+48);
  258.         write_date( 'W');
  259. }


  260. void delay(uint z)
  261. {
  262.         uint x,y;
  263.         for(x=z;x>0;x--)
  264.         {
  265.                 for(y=0;y<=112;y++)
  266.                 {
  267.                 }
  268.         }
  269. }
  270. void write_command(uchar command)
  271. {
  272.         lcddatecommand=0;
  273.         lcdwrite=0;
  274.         P0=command;
  275.         delay(1);
  276.         lcde=1;
  277.         delay(1);
  278.         lcde=0;
  279. }
  280. void write_date(uchar date)
  281. {
  282.         lcddatecommand=1;
  283.         lcdwrite=0;
  284.         P0=date;
  285.         delay(1);
  286.         lcde=1;
  287.         delay(1);
  288.         lcde=0;
  289. }
  290. void LCDinit()
  291. {
  292.         lcde=0;
  293.         write_command(0x38);//设置16*2显示,5*7点阵,8位数据接口
  294.         write_command(0x0f);//设置开显示,不显示光标
  295.         write_command(0x06);// 写一个字符后地址指针加1
  296.         write_command(0x0C);
  297.         write_command(0x80);

  298.         write_command(0x80+0x40);
  299.         for(i=0;i<8;i++)
  300.         {
  301.                 write_date(secondline[i]);
  302.                 delay(1);
  303.         }
  304. }
  305. void Time0init()
  306. {
  307.         TMOD=0x01;//开启定时器1
  308.         TH0=(65536-50000)/256;
  309.         TL0=(65536-50000)%256;
  310.         EA=1;
  311.         ET0=1;
  312.         TR0=1;
  313. }
  314. void Clockinit()
  315. {
  316.         hour=0;
  317.         minutes=0;
  318.         seconds=0;
  319.         count=0;
  320.         num=0;
  321. }
  322. void display(uchar hour,uchar minutes,uchar seconds)//接收并发送数据到液晶屏幕
  323. {
  324.         uchar hourge,hourshi,minutesshi,minutesge,secondsshi,secondsge;
  325.         hourshi=hour/10;
  326.         hourge=hour%10;
  327.         write_command(0x80+0x40);
  328.         write_date(hourshi+48);
  329.         delay(1);
  330.         write_date(hourge+48);
  331.         delay(1);

  332.         minutesshi=minutes/10;
  333.         minutesge=minutes%10;
  334.         write_command(0x0C);
  335.         write_command(0x80+0x43);
  336.         write_date(minutesshi+48);
  337.         delay(1);
  338.         write_date(minutesge+48);
  339.         delay(1);

  340.         secondsshi=seconds/10;
  341.         secondsge=seconds%10;
  342.         write_command(0x80+0x46);
  343.         write_date(secondsshi+48);
  344.         delay(1);
  345.         write_date(secondsge+48);
  346.         delay(1);
  347. }
  348. void revise()
  349. {
  350.         if(K1==0)
  351.         {
  352.                 delay(5);
  353.                 if(K1==0)
  354.                 {
  355.                         cnt++;//计数第几次按下
  356.                         TR0=0;
  357.                 }
  358.                 while(!K1);
  359.                 delay(5);
  360.                 while(!K1);
  361.         }
  362.         if(cnt==1)//第一次按下,调整秒钟,调整时秒钟有光标闪烁
  363.         {
  364.                 write_command(0x80+0x46);
  365.                 write_command(0x0f);
  366.                 if(K2==0)
  367.                 {
  368.                         delay(5);
  369.                         if(K2==0)
  370.                         {
  371.                                 seconds++;
  372.                                 if(seconds==60)
  373.                                 {
  374.                                         seconds=0;
  375.                                 }
  376.                         }
  377.                         while(!K2);
  378.                         delay(5);
  379.                         while(!K2);
  380.                 }
  381.                 if(K3==0)
  382.                 {
  383.                         delay(5);
  384.                         if(K3==0)
  385.                         {
  386.                                 seconds--;
  387.                                 if(seconds==-1)//here is a bug
  388.                                 {
  389.                                         seconds=59;
  390.                                 }
  391.                         }
  392.                         while(!K3);
  393.                         delay(5);
  394.                         while(!K3);
  395.                 }
  396.         }

  397.         if(cnt==2)//第二次按下,调整分钟,调整时秒钟有光标闪烁
  398.         {
  399.                 write_command(0x80+0x43);
  400.                 write_command(0x0f);
  401.                 if(K2==0)
  402.                 {
  403.                         delay(5);
  404.                         if(K2==0)
  405.                         {
  406.                                 minutes++;
  407.                                 if(minutes==60)
  408.                                 {
  409.                                         minutes=0;
  410.                                 }
  411.                         }
  412.                         while(!K2);
  413.                         delay(5);
  414.                         while(!K2);
  415.                 }
  416.                 if(K3==0)
  417.                 {
  418.                         delay(5);
  419.                         if(K3==0)
  420.                         {
  421.                                 minutes--;
  422.                                 if(minutes==-1)//here is a bug
  423.                                 {
  424.                                         minutes=59;
  425.                                 }
  426.                         }
  427.                         while(!K3);
  428.                         delay(5);
  429.                         while(!K3);
  430.                 }
  431.         }
  432.         if(cnt==3)//第三次按下,调整时钟,调整时秒钟有光标闪烁
  433.         {
  434.                 write_command(0x80+0x40);
  435.                 write_command(0x0f);
  436.                 if(K2==0)
  437.                 {
  438.                         delay(5);
  439.                         if(K2==0)
  440.                         {
  441.                                 hour++;
  442.                                 if(hour==24)
  443.                                 {
  444.                                         hour=0;
  445.                                 }
  446.                         }
  447.                         while(!K2);
  448.                         delay(5);
  449.                         while(!K2);
  450.                 }
  451.                 if(K3==0)
  452.                 {
  453.                         delay(5);
  454.                         if(K3==0)
  455.                         {
  456.                                 hour--;
  457.                                 if(hour==-1)//here is a bug
  458.                                 {
  459.                                         hour=23;
  460.                                 }
  461.                         }
  462.                         while(!K3);
  463.                         delay(5);
  464.                         while(!K3);
  465.                 }
  466.         }
  467.         if(cnt==4)
  468.         {
  469.                 TR0=1;
  470.                 cnt=0;
  471.         }
  472. }
  473. void main()
  474. {
  475.         INA219_Init();
  476.         LCDinit();
  477.         Time0init();
  478.         Clockinit();
  479.         Delay_us(2000);
  480.         RefreshData();
  481.         while(1)
  482.         {
  483.                 revise();
  484.                 if(count>=19)
  485.                 {
  486.                         display(hour,minutes,seconds);
  487.                         RefreshData();
  488.                 }
  489.         }
  490. }
  491. void Time0() interrupt 1 using 2
  492. {
  493.         TH0=(65536-50000)/256;
  494.         TL0=(65536-50000)%256;
  495.         count++;
  496.         if(count==20)
  497.         {
  498.                 count=0;
  499.                 seconds++;
  500.                 if(seconds==60)
  501.                 {
  502.                         seconds=0;
  503.                         minutes++;
  504.                         if(minutes==60)
  505.                         {
  506.                                 minutes=0;
  507.                                 hour++;
  508.                                 if(hour==24)
  509.                                 {
  510.                                         hour=0;
  511.                                 }
  512.                         }
  513.                 }
  514.         }
  515. }

复制代码





回复

使用道具 举报

6#
ID:155507 发表于 2021-2-22 14:23 | 只看该作者
Kituro 发表于 2021-2-20 17:50
好像确实应该这样...
不过我把A1,A0和SDA连起来之后这个IC还是无响应nack的状态...

我已经测试过了

是Proteus仿真软件的问题, 这个INA219仿真I2C设备, 电压电流监测模块 , 只能工作的地址是 0x80, 0x82
其他地址将无法正常工作
回复

使用道具 举报

7#
ID:884307 发表于 2021-2-26 20:33 | 只看该作者
angmall 发表于 2021-2-22 14:23
我已经测试过了

是Proteus仿真软件的问题, 这个INA219仿真I2C设备, 电压电流监测模块 , 只能工作的地 ...

非常感谢!
我现在是在自学电子设计, 对于布线和PCB设计之类的知识又一窍不通, 而这些又是必要的
能不能请问一下在哪里能学习这些知识呢?
回复

使用道具 举报

8#
ID:155507 发表于 2021-2-26 23:58 | 只看该作者
Kituro 发表于 2021-2-26 20:33
非常感谢!
我现在是在自学电子设计, 对于布线和PCB设计之类的知识又一窍不通, 而这些又是必要的
能不能 ...

做PCB板就比较简单了。只要懂得使用Protel软件或 AltiumDesigner软件就没问题了。但要想做的板子布局美观、布线合理还得费一番功夫了。
    娴熟的单片机C语言编程、会使用Protel软件或 AltiumDesigner软件设计PCB板和具备一定的英文阅读能力,你就是一个遇强则强的单片机高手了。

请看这个类似参考
http://www.51hei.com/bbs/mcu-pcb-1.html


可以手动布线和自动布线相结 和先排大件,再放小件,坚持画几块板,就不会感觉难了
前期布局最重要,刚学没必要纠结怎么走线 多画一些板子,自然就找到感觉了
最好是买本书来看,结合书本理论实际动手,多画几块板子
多看看高手的排线,自己多练练就有自己的思路了
好像有一些布线规则,找找看
回复

使用道具 举报

9#
ID:884307 发表于 2021-2-27 21:52 | 只看该作者
angmall 发表于 2021-2-22 11:11
你的地址写错了

感谢你的建议!
问一下, 这个

  1. #define INA219_RD_Operation 0x81
  2. #define INA219_WR_Operation 0x80
复制代码

是什么东西, 在文档里没看到0x80这个数字出现, 根据手册第一次发送的应该是slave address, 来指定A0和A1采样的管脚
为什么要发送这个 INA219_RD_Operation 呢? 有什么意义吗?
回复

使用道具 举报

10#
ID:155507 发表于 2021-2-27 23:06 | 只看该作者
Kituro 发表于 2021-2-27 21:52
感谢你的建议!
问一下, 这个
是什么东西, 在文档里没看到0x80这个数字出现, 根据手册第一次发送的应该 ...


8.5.6写入和读取INA219
通过将适当的值写入寄存器指针来访问INA219上的特定寄存器。有关寄存器和相应地址的完整列表,请参见表2。如图18所示,寄存器指针的值是R / W位为LOW的从设备地址字节后的第一个字节。
对INA219的每次写操作都需要为寄存器指针指定一个值。
写入寄存器始于主机发送的第一个字节。该字节是从机地址,R / W位为低电平。
然后,INA219确认收到有效地址。主机发送的下一个字节是将要写入数据的寄存器的地址。
该寄存器地址值将寄存器指针更新为所需的寄存器。接下来的两个字节被写入寄存器指针所指向的寄存器。 INA219确认收到每个数据字节。主机可以通过产生START或STOP条件来终止数据传输。
从INA219读取时,通过写操作存储在寄存器指针中的最后一个值确定在读操作期间读取哪个寄存器。要更改读取操作的寄存器指针,必须将新值写入寄存器指针。
该写操作通过发出一个R / W位为LOW的从机地址字节,然后是寄存器指针字节来完成。
不需要其他数据。然后,主机产生一个START条件,并发送具有R / W位为高的从机地址字节,以启动读取命令。
下一个字节由从机发送,是寄存器指针指示的寄存器的最高有效字节。该字节之后是来自主机的应答。
然后从机发送最低有效字节。主机确认收到数据字节。主机可以通过生成一个
接收到任何数据字节或生成START或STOP条件后,不应答。如果需要从同一寄存器重复读取,则不必连续发送寄存器指针字节;否则,无需执行任何操作。 INA219保留寄存器指针值,直到下一次写操作对其进行更改为止。
图15和图16分别显示了写和读操作时序图。请注意,寄存器字节先发送最高有效字节,然后再发送最低有效字节。










第一次发送 0x80 寄存器 0x02 读取电压  发送 0x81 读取 INA219 发送 0x5D 0xAA    ---> 0x5DAA = 23978/2 =11989mV





回复

使用道具 举报

11#
ID:884307 发表于 2021-2-28 10:32 | 只看该作者
angmall 发表于 2021-2-27 23:06
8.5.6写入和读取INA219
通过将适当的值写入寄存器指针来访问INA219上的特定寄存器。有关寄存器和相应 ...

好的好的
那这个A0和A1到底是做什么的, 文档说是指定从设备地址, 那这个表格是什么意思?
回复

使用道具 举报

12#
ID:155507 发表于 2021-2-28 11:11 | 只看该作者
Kituro 发表于 2021-2-28 10:32
好的好的
那这个A0和A1到底是做什么的, 文档说是指定从设备地址, 那这个表格是什么意思?

I2C 总线是一双线串行总线, 它提供一小型网络系统,为总线上的电路共享公共的总线。
总线上的器件, 每个器件都有自己的地址  该INA219器件共有16个地址, 那你最多可以控制16个器件
回复

使用道具 举报

13#
ID:884307 发表于 2021-2-28 11:25 | 只看该作者
angmall 发表于 2021-2-28 11:11
I2C 总线是一双线串行总线, 它提供一小型网络系统,为总线上的电路共享公共的总线。
总线上的器件, 每 ...

我不明白的是, 比如当slave address为1000000时, A1和A0都对应到GND上(或者是VSS, SDA, SCL或其他管脚上)对A0和A1的值有什么影响吗?
也就是说, 表格中不同的slave address的值, 是否对A0和A1的值有影响?
回复

使用道具 举报

14#
ID:155507 发表于 2021-2-28 20:27 | 只看该作者
该个是因果关系
因为你需要为每个INA219器件使用不同的地址,因此你需要将A0和A1引脚连接到不同的值。

回复

使用道具 举报

15#
ID:420836 发表于 2021-2-28 23:53 | 只看该作者
好问题,读后有帮助。
回复

使用道具 举报

16#
ID:884307 发表于 2021-3-21 15:26 | 只看该作者
angmall 发表于 2021-2-28 20:27
该个是因果关系
因为你需要为每个INA219器件使用不同的地址,因此你需要将A0和A1引脚连接到不同的值。

谢谢, 问题完美解决!
抱歉过了这么久才来回复你.....
回复

使用道具 举报

17#
ID:891529 发表于 2021-3-21 15:41 | 只看该作者
建议描述问题时候,带上使用的环境和各参数
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表