数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 253|回复: 9

[手持表] 不用编程器&来回拆焊写个程序读写DTM0660/HY12P66之流的存储芯片

[复制链接]
发表于 昨天 00:42 | 显示全部楼层 |阅读模式




一个破表,Victor的VC9801A+  PCB标:2013-07-09 9801(V0.7)
安装的EEPROM是: 丝印T24C08A 13SD2

原来发过帖,DCV档不切换档位,数值就不变。
板印HY12P66,正好拿来练手改9999。

编程器不爱用,每次得拆焊,感觉老费劲了,买了一个就不知道仍哪去了。

直接上Arduino Uno,空机连接AT24C08.
用Nano也可以,不过Uno自带单独的I2C接口,用起来方便多了。

接线:
Uno     AT24C08
----      -----------
3.3V    #8:Vcc
GND    #4:GND
SCL     #6: SCL
SDA     #5: SDA

另外24C08的WP脚要连到GND上,才能对存储器进行写入,不过这样表会进入校准状态,
需要写完后再断开。

这个表没有把上面的除供电外的接口引出,所以还是需要焊上几根引线,再杜邦线连到Uno板子上。

结果:
1. 单独某地址读出成功。
2. 全部到处成功,由于串口打印导出为文本格式,还需要另外的程序转换为二进制bin文件。
   写了个python程序搞定。已经能在大神的《万用表校准编辑器》中打开了。
   不过还是有很多的未知项,以后再研究。
3. 改写某个地址的单字节数据成功。




直接贴代码:
// ================= 代码开始 ==================

/*
型号       容量       器件寻址字节(8位)   一次装载字节数 (页长度)
AT24C08    1024×8    1010A2P1P0 R/W     16
外壳:VC9801A+  PCB标:2013-07-09 9801(V0.7)
安装的EEPROM是: 丝印T24C08A 13SD2*/
#include <Wire.h>

const byte DEVADDR = 0x50;

#include <Arduino_FreeRTOS.h>
#include <semphr.h>
#include <Wire.h>
#define SP  Serial.print
#define SPL Serial.println

void TaskSerial( void *pvParameters );
void TaskBlink ( void *pvParameters );

SemaphoreHandle_t activateActuatorSem;

char serin[64];
unsigned int iser = 0;

void setup() {
  Wire.begin();
  Serial.begin(19200);
  while (!Serial) {;}
  SPL(F("\n\n<OSSER24C08>"));
  pinMode(LED_BUILTIN, OUTPUT);
  
  activateActuatorSem = xSemaphoreCreateBinary();
  if ( activateActuatorSem != NULL ) {
    xSemaphoreGive( activateActuatorSem );  
  }
  xTaskCreate(TaskBlink, "LED", 128, NULL, 2, NULL);
  xTaskCreate(TaskSerial, "SER", 128, NULL, 1, NULL);
}

void loop() {}

void TaskSerial( void *pvParameters ) {
  (void) pvParameters;
  
  for (;;) {   
    if(Serial.available()>0){
      char c = Serial.read();
      if (c == '\n' || iser > 60) {
        serin[iser]='\0';
        SP(serin);
        iser = 0;
        Process_SerIN();
        xSemaphoreGive(activateActuatorSem);
      } else {
        serin[iser++] = c;
      }
    }
    vTaskDelay( 250 / portTICK_PERIOD_MS );
  }
}

void TaskBlink(void *pvParameters) {
  (void) pvParameters;
  for (;;) {
    xSemaphoreTake(activateActuatorSem, portMAX_DELAY);
    SPL(F("/LED"));
    for (byte lp=0;lp<5;lp++){
      digitalWrite(LED_BUILTIN, HIGH);  
      vTaskDelay( 250 / portTICK_PERIOD_MS );
      digitalWrite(LED_BUILTIN, LOW);
      vTaskDelay( 250 / portTICK_PERIOD_MS );
    }
  }
}

void Process_SerIN(){
  if(serin[0]=='d' && serin[1]=='u' && serin[2]=='m' && serin[3]=='p'){
    SPL("=D:");
    eeprom_dump(DEVADDR, 0, 512);
    SPL();
    return;
  }

  // read a byte
  if(serin[0]=='r' && serin[1]=='e' && serin[2]=='a' && serin[3]=='d'){
    SP("=R:&");
    unsigned int ii=4;
    for (ii=4;ii<9;ii++){
      if (serin[ii] == '\0'){
        if ((ii-4)%2 !=0){
          SPL(F("BadDataAddr"));
          return;
        } else {
          break;/
        }
      }
    }
   
    size_t hexStrLen = ii-4;
    unsigned int dataAddr = 0;
    for (size_t i = 0; i < (hexStrLen/2); i++){
       dataAddr = dataAddr*256+composeByteSer(i*2+4);
    }
    SP(dataAddr, HEX);
    byte b = eeprom_read_byte(DEVADDR, dataAddr);
    SP("=");   
    SPL(b, HEX);
    return;
  }

  if(serin[0]=='w'&&serin[1]=='r'&&serin[2]=='i'&&serin[3]=='t'&&serin[4]=='e'){
    SP("=W:&");
    if (!(serin[7] == ' ')){
      SPL(F("BadAddr"));
      return;
    }
    unsigned int dataAddr = 0;
   
    dataAddr = composeByteSer(5);
    SP(dataAddr,  HEX);
    if (serin[7] == ' ' ){
      if( serin[10] != '\0'){
        SP(F("BadVal"));
        return;
      } else {
        dataVal = composeByteSer(8);
      }
    }
    SP("=");
    SPL(dataVal,  HEX);

    // 04. Write the data
    byte b = eeprom_read_byte(DEVADDR, dataAddr);
    SP(b, HEX); SP("->");delay(50);
   
    eeprom_write_byte(DEVADDR, dataAddr, dataVal);
    delay(50);
   
    b = eeprom_read_byte(DEVADDR, dataAddr);
    SPL(b, HEX);
   
    return;
  }
}

byte composeByteSer(byte i0){
  return (serin[i0]   % 32 + 9) % 25 * 16
       + (serin[i0+1] % 32 + 9) % 25;
}

int eeprom_read_byte(byte at24Addr, unsigned dataAddr) {
   byte rdata = -1;
   byte devAddr = at24Addr | ((dataAddr >> 8) & 0x07);

   Wire.beginTransmission(devAddr);
   Wire.write(int(dataAddr));
   Wire.endTransmission();
   Wire.requestFrom(int(devAddr), 1);
   if (Wire.available()) {
       rdata = Wire.read();
   }
   delay(100);
   return rdata;
}

// buffer 长度需要< 30.
int eeprom_read_buffer(byte deviceaddr, unsigned dataAddr, byte * buffer, byte length) {
   byte devAddr = deviceaddr | ((dataAddr >> 8) & 0x07);
   
   Wire.beginTransmission(devAddr);
   Wire.write(int(dataAddr));
   Wire.endTransmission();

   Wire.requestFrom(devAddr, length);
   int i;
   for (i = 0; i < length && Wire.available(); i++) {
       buffer[i] = Wire.read();
   }
   return i;
}


void eeprom_dump(byte devAddr, unsigned dataAddr, unsigned length) {
   unsigned startAddr = dataAddr & (~0x0f);
   unsigned stopAddr  = (dataAddr + length + 0x0f) & (~0x0f);
   for (unsigned i = startAddr; i < stopAddr; i += 16) {
       byte buffer[16];
       char outbuf[6];
       sprintf(outbuf, "%03x: ", i);
       SP(outbuf);
       eeprom_read_buffer(devAddr, i, buffer, 16);
       for (int j = 0; j < 16; j++) {
           sprintf(outbuf, "%02x ", buffer[j]);
           SP(outbuf);
       }
       SPL();
   }
}

void eeprom_write_byte(byte devAddr0, int dataAddr, byte dataVal) {
   byte devAddr = devAddr0 | ((dataAddr >> 8) & 0x07);
   Wire.beginTransmission(devAddr);
   Wire.write(int(dataAddr));
   Wire.write(int(dataVal));
   Wire.endTransmission();
   delay(10);
}


// ================= 代码结束 ==================



已经成功改成6千字,高级用法还不会.....




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

打赏

参与人数 2家元 +54 收起 理由
zto中通快递 + 27
jf201006 + 27 謝謝分享

查看全部打赏

发表于 昨天 10:45 | 显示全部楼层
万用表校准编辑器 求个下载地址
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 10:54 | 显示全部楼层
gy9319 发表于 2025-7-25 10:45
万用表校准编辑器 求个下载地址

就在本区:https://www.mydigit.cn/thread-461598-1-2.html
回复 支持 反对

使用道具 举报

发表于 昨天 14:21 | 显示全部楼层
就是读写一个24系列的芯片,楼主搞得太复杂了点。
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 16:04 | 显示全部楼层
jiuweiljp 发表于 2025-7-25 14:21
就是读写一个24系列的芯片,楼主搞得太复杂了点。

要一点点的测修改量,用编程器的话就得反复拆,这个就WP搭一下就能改了 等于在线调试
回复 支持 反对

使用道具 举报

发表于 昨天 18:28 | 显示全部楼层
虽然我看不懂,但是我依然承认这个UP很牛逼,哈哈哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 19:07 | 显示全部楼层
将导出的字符形式的数据,转换为二进制文件
的python程序:

"""
==== 数据====
3f 5a c7 ce 0f 0f 06 20 ff 52 00 f0 00 00 be 03
70 17 cf 07 b4 00 6e 50 64 4b 0a 0a 0a ff 40 ff
bc 98 9e 82 64 00 96 00 00 80 00 80 00 80 00 80
4e 02 09 b3 09 09 c1 d9 0a 91 1c 0a a2 04 0a 00
... ...
"""

import struct

if __name__ == "__main__":
        bytes_filename = 'your_dmm_24c08_dump.txt'
        fin = open(bytes_filename, 'r')
        fout = open("your_dmm_24c08a.bin", "wb")
        for line in fin:
                line = line.strip()
                #print(ln)
                bytes = line.split(' ')
                #print(bytes)
                for bt in bytes:
                        #print(int(bt, 16))
                        #print(bt, end ='')
                        inta = int(bt,base=16)
                        print(inta, end =' ')
                        fout.write(inta.to_bytes(1,"big"))
                print()
回复 支持 反对

使用道具 举报

发表于 昨天 21:08 | 显示全部楼层
代码好复杂,还是拿个编程器吧
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-26 11:49 , Processed in 0.187200 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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