矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
楼主: scoopydoo

[DIY] 迷你型可编程快速脉冲发生器 PulseGen 433-3949

  [复制链接]
     
发表于 2024-4-18 20:20:52 | 显示全部楼层
本帖最后由 量子隧道 于 2024-4-18 20:43 编辑

哈哈哈,我可能悟出来了超长时基是如何实现的了!
明天编辑个详细的图贴上来讨论。
回复 支持 反对

使用道具 举报

     
发表于 2024-7-6 12:44:01 | 显示全部楼层
可以共享下测试的单片机源码么,我这也画了电路板,用aduino程序,脉冲出不来
微信图片_20240706124257.png
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-6 18:31:58 | 显示全部楼层
本帖最后由 scoopydoo 于 2024-7-6 19:14 编辑
maozheng110 发表于 2024-7-6 12:44
可以共享下测试的单片机源码么,我这也画了电路板,用aduino程序,脉冲出不来


你用的是 Arduino,俺用的是 STM32 的 HAL 库,代码恐怕无法通用。不知道你的问题出在哪里,俺觉得最有可能的是两部分。

第一个就是通讯协议,它咋一看好像用的是 I2C,但是仔细看还是有区别的,这部分俺自己写了代码,然后在主程序里面调用初始化函数就可以了。

第二个就是寄存器内容的初始化,这部分如果只是想要出波形还是很简单的。

下面的代码仅供参考:

max3949.h
  1. #pragma once

  2. #include "main.h"

  3. /**
  4.   * @brief  MAX3949 registers address enumeration
  5.   */
  6. typedef enum
  7. {
  8.   MAX3949_REG_TXCTRL = 5U,  // 0x05 Transmitter Control Register
  9.   MAX3949_REG_TXSTAT1,      // 0x06 Transmitter Status Register 1
  10.   MAX3949_REG_TXSTAT2,      // 0x07 Transmitter Status Register 2
  11.   MAX3949_REG_SETIBIAS,     // 0x08 Bias Current Setting Register
  12.   MAX3949_REG_SETIMOD,      // 0x09 Modulation Current Setting Register
  13.   MAX3949_REG_IMODMAX,      // 0x0A Maximum Modulation Current Setting Register
  14.   MAX3949_REG_IBIASMAX,     // 0x0B Maximum Bias Current Setting Register
  15.   MAX3949_REG_MODINC,       // 0x0C Modulation Current Increment Setting Register
  16.   MAX3949_REG_BIASINC,      // 0x0D Bias Current Increment Setting Register
  17.   MAX3949_REG_MODECTRL,     // 0x0E Mode Control Register
  18.   MAX3949_REG_FMSK,         // 0x0F Fault Mask Register
  19.   MAX3949_REG_SETTXDE,      // 0x10 Transmitter Deemphasis Control Register
  20.   MAX3949_REG_SETTXEQ       // 0x11 Transmitter Equalization Control Register
  21. } MAX3949_Register;

  22. #define MAX3949_REG_COUNT (MAX3949_REG_SETTXEQ + MAX3949_REG_TXCTRL - 1)

  23. #define MAX3949_TXCTRL_POL_NORMAL  0x02
  24. #define MAX3949_TXCTRL_EN_ENABLE   0x01
  25. #define MAX3949_MODECTRL_NORMAL    0x00
  26. #define MAX3949_MODECTRL_SETUP     0x12
  27. #define MAX3949_MODECTRL_BROADCAST 0xC9
  28. #define MAX3949_FMSK_ALL           0x7F

  29. /**
  30.   * @brief   MAX3949 initial structure definition
  31.   */
  32. typedef struct
  33. {
  34.   GPIO_TypeDef* CSEL_Port;
  35.   uint16_t CSEL_Pin;
  36.   GPIO_TypeDef* CLK_Port;
  37.   uint16_t CLK_Pin;
  38.   GPIO_TypeDef* DATA_Port;
  39.   uint16_t DATA_Pin;
  40. } MAX3949_InitTypeDef;

  41. HAL_StatusTypeDef UHAL_MAX3949_Init(MAX3949_InitTypeDef* MAX3949_InitStruct);
  42. uint8_t UHAL_MAX3949_ReadReg(MAX3949_Register reg);
  43. void UHAL_MAX3949_WriteReg(MAX3949_Register reg, uint8_t data);
复制代码


max3949.h
  1. #include "max3949.h"
  2. #include "stdbool.h"

  3. #define MAX3949_ADDR_SHIFT 9U
  4. #define MAX3949_READ_MASK 0x01FFU
  5. #define MSB_OF_UINT16 0x8000U

  6. static bool Initialed = false;
  7. static MAX3949_InitTypeDef InitStruct;

  8. static void Delay(void)
  9. {
  10.   static __IO uint32_t t = 0;
  11.   t++;
  12. }

  13. static void MAX3949_CSEL_Write(GPIO_PinState PinState)
  14. {
  15.   HAL_GPIO_WritePin(InitStruct.CSEL_Port, InitStruct.CSEL_Pin, PinState);
  16. }

  17. static void MAX3949_CLK_Write(GPIO_PinState PinState)
  18. {
  19.   HAL_GPIO_WritePin(InitStruct.CLK_Port, InitStruct.CLK_Pin, PinState);
  20. }

  21. static void MAX3949_DATA_Write(GPIO_PinState PinState)
  22. {
  23.   HAL_GPIO_WritePin(InitStruct.DATA_Port, InitStruct.DATA_Pin, PinState);
  24. }

  25. static GPIO_PinState MAX3949_SDA_Read(void)
  26. {
  27.   return(HAL_GPIO_ReadPin(InitStruct.DATA_Port, InitStruct.DATA_Pin));
  28. }

  29. HAL_StatusTypeDef UHAL_MAX3949_Init(MAX3949_InitTypeDef* MAX3949_InitStruct)
  30. {
  31.   InitStruct.CSEL_Port = MAX3949_InitStruct->CSEL_Port;
  32.   InitStruct.CSEL_Pin = MAX3949_InitStruct->CSEL_Pin;
  33.   InitStruct.CLK_Port = MAX3949_InitStruct->CLK_Port;
  34.   InitStruct.CLK_Pin = MAX3949_InitStruct->CLK_Pin;
  35.   InitStruct.DATA_Port = MAX3949_InitStruct->DATA_Port;
  36.   InitStruct.DATA_Pin = MAX3949_InitStruct->DATA_Pin;
  37.   MAX3949_CSEL_Write(GPIO_PIN_RESET);
  38.   MAX3949_CLK_Write(GPIO_PIN_RESET);
  39.   MAX3949_DATA_Write(GPIO_PIN_RESET);
  40.   Initialed = true;
  41.   return(HAL_OK);
  42. }

  43. uint8_t UHAL_MAX3949_ReadReg(MAX3949_Register reg)
  44. {
  45.   if (!Initialed) return(0);

  46.   uint8_t result;
  47.   MAX3949_CSEL_Write(GPIO_PIN_SET);
  48.   uint16_t address = (reg << MAX3949_ADDR_SHIFT) | MAX3949_READ_MASK;
  49.   MAX3949_CLK_Write(GPIO_PIN_RESET);
  50.   for (uint16_t i = 0; i < 16; i++)
  51.   {
  52.     MAX3949_DATA_Write(address & MSB_OF_UINT16 ? GPIO_PIN_SET : GPIO_PIN_RESET);
  53.     MAX3949_CLK_Write(GPIO_PIN_SET);
  54.     Delay();
  55.     address <<= 1;
  56.     result <<= 1;
  57.     result |= MAX3949_SDA_Read();
  58.     MAX3949_CLK_Write(GPIO_PIN_RESET);
  59.   }
  60.   Delay();
  61.   MAX3949_CLK_Write(GPIO_PIN_SET);
  62.   Delay();
  63.   MAX3949_CSEL_Write(GPIO_PIN_RESET);
  64.   MAX3949_DATA_Write(GPIO_PIN_SET);
  65.   Delay();
  66.   return(result);
  67. }

  68. void UHAL_MAX3949_WriteReg(MAX3949_Register reg, uint8_t data)
  69. {
  70.   if (!Initialed) return;

  71.   MAX3949_CSEL_Write(GPIO_PIN_SET);
  72.   uint16_t address_data = (reg << MAX3949_ADDR_SHIFT) | data;
  73.   MAX3949_CLK_Write(GPIO_PIN_RESET);
  74.   for (uint16_t i = 0; i < 16; i++)
  75.   {
  76.     MAX3949_DATA_Write(address_data & MSB_OF_UINT16 ? GPIO_PIN_SET : GPIO_PIN_RESET);
  77.     MAX3949_CLK_Write(GPIO_PIN_SET);
  78.     Delay();
  79.     address_data <<= 1;
  80.     MAX3949_CLK_Write(GPIO_PIN_RESET);
  81.   }
  82.   Delay();
  83.   MAX3949_CLK_Write(GPIO_PIN_SET);
  84.   Delay();
  85.   MAX3949_CSEL_Write(GPIO_PIN_RESET);
  86.   MAX3949_DATA_Write(GPIO_PIN_SET);
  87.   Delay();
  88. }
复制代码



评分

2

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-6 19:54:58 | 显示全部楼层
刚刚自己又看了一眼代码,有些命名和数据类型的小问题,还好不耽误正常运行 ......
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-7 02:40:41 | 显示全部楼层
刚看完英格兰和瑞士的点球大战,又扫了一眼代码,发现了一个极其愚蠢的错误,尽管这个宏定义并没有用到!

  1. #define MAX3949_REG_COUNT (MAX3949_REG_SETTXEQ + MAX3949_REG_TXCTRL - 1)
复制代码


应该是

  1. #define MAX3949_REG_COUNT (MAX3949_REG_SETTXEQ - MAX3949_REG_TXCTRL + 1)
复制代码


真不知道当时脑子里在想些啥 ......
回复 支持 反对

使用道具 举报

     
发表于 2024-7-7 10:13:00 | 显示全部楼层
谢谢,我参考的这个https://www.eevblog.com/forum/be ... 49-laser-driver-ic/
max3949.cpp
// Created by SoaSystem Engineering 2020 for Pulse-Duino Project
// In God The Merciful, The Provider of Intelligence and Knowledge

// software based 3-wires communication, custom I2C protocol
// to emulate open drain (I2C) IO with pull up resistors present

#include "max3949.h"

void csel_low() {
    pinMode(CSEL_PIN, OUTPUT);
}

void csel_high() {
    pinMode(CSEL_PIN, INPUT);
}

void sda_low() {
    pinMode(SDA_PIN, OUTPUT);
}

void sda_high() {
    pinMode(SDA_PIN, INPUT);
}

void scl_low() {
    pinMode(SCL_PIN, OUTPUT);
}

void scl_high() {
    pinMode(SCL_PIN, INPUT);
}

// initialize serial comm
void init_comm() {
    csel_high();
    scl_low();
    delayMicroseconds(COMM_DELAY);
}

// finish comm, preparing idle state
void close_comm() {
    delayMicroseconds(COMM_WIDTH);
    scl_high();//input
    sda_high();//input
    csel_low();//output
}

void send_addr(byte addr) {
    byte bits = 7;

    // sending 7 bits register address
    while (bits--) {


        // send data (MSB) while clock low
        if (addr & 128) {
            sda_high();
        } else {
            sda_low();
        };
        delayMicroseconds(COMM_WIDTH);

        scl_high();
        delayMicroseconds(COMM_WIDTH);
        scl_low();
        addr <<= 1;
    };
}

byte read_value() {
    byte res, bits = 8;

    // reading 8 bits register value
    while (bits--) {

        // ready receiving register value (clock low)
        delayMicroseconds(COMM_WIDTH);

        // MAX3949 should start sending next bit of register value here
        scl_high();
        delayMicroseconds(COMM_WIDTH);
        scl_low();

        // get next bit
        
        
        if (digitalRead(SDA_PIN)) {
            res |= 1;
        } else {
            res &= 254;
        };
        res <<= 1;//MSB first
    };

    return res;
}

void send_value(byte value) {
    byte bits = 8;

    // sending 8 bits register value
    while (bits--) {

        // send data (MSB) while clock low
        if (value & 128) {
            sda_high();
        } else {
            sda_low();
        };
        value <<= 1;
        delayMicroseconds(COMM_WIDTH);

        scl_high();
        delayMicroseconds(COMM_WIDTH);
        scl_low();
    };
}

void write_register(byte addr, byte value) {
    init_comm();
    send_addr(addr);

    // send write flag
    sda_low();
    delayMicroseconds(COMM_WIDTH);
    scl_high();
    delayMicroseconds(COMM_WIDTH);
    scl_low();

    send_value(value);
    close_comm();
}

// just to make sure
void MAX3949_Init() {
    pinMode(CSEL_PIN, OUTPUT);
    digitalWrite(CSEL_PIN, LOW);
    pinMode(SDA_PIN, OUTPUT);
    digitalWrite(SDA_PIN, LOW);
    pinMode(SCL_PIN, OUTPUT);
    digitalWrite(SCL_PIN, LOW);
    csel_low();
    sda_high();
    scl_high();
}

byte MAX3949_Read_Register(byte addr) {
    init_comm();
    send_addr(addr);

    // send read flag
    sda_high();
    delayMicroseconds(COMM_WIDTH);
    scl_high();
    delayMicroseconds(COMM_WIDTH);
    scl_low();

    byte res = read_value();
    close_comm();
    return res;
}

void MAX3949_Write_Register(byte addr, byte value, bool broadcast) {
    if (addr != 0x0E) {

        // write in broadcast mode
        if (broadcast) {
            write_register(0x0E, 0xC9);
   
        // write in setup mode
        } else {
            write_register(0x0E, 0x12);
        };

        delayMicroseconds(COMM_WIDTH);
    };

    // write the register
    write_register(addr, value);


main

// Created by SoaSystem Engineering 2020 for Pulse-Duino Project
// In God The Merciful, The Provider of Intelligence and Knowledge

// receiver: MAX3949 Laser Driver IC
// ref: MAX3949 11.3Gbps laser driver.pdf (page 21)
// code for Arduino Nano (atMega328P CKOUT fuse programmed for pin D8 (PB0/CLKO) as 16MHz clock output, page 36, 86, 301)

#include "max3949.h"

// default TXCTRL register value to normal polarity (TX_POL = 1),
// de-emphasize 9% and transmit active (TX_EN = 1)
#define TXCTRL_VAL B00011011

// other MAX3949 parms
#define IMAX 245 // laser maximum current modulation
#define IMIN 5 // laser minimum current modulation
byte cur_imod; // currently set laser current modulation

#define LED_PIN 13 // warning led D13
#define FAULT_DETECT A2 // fault pin from MAX3949
#define CLK_CTL 6 // clock suppression control

#define ANA1_MAX 30 // resolution of analog trimpot value
#define ANA1_PIN A1 // analog trimpot value input

#define LED_RATE 1000 // milliseconds
#define LED_MODULO (LED_RATE / 8)
byte led_bit = 0;

// 2 seconds delay timer
#define ELAPSE2S 2000
unsigned long tmr2sta, tmr2cur;

// analog trimpot adc value
int ana1_val = 0;



#define ledOn() digitalWrite(LED_PIN, HIGH)
#define ledOff() digitalWrite(LED_PIN, LOW)

// clock control cannot produce output HI. circuit may get damaged
#define clockOn() pinMode(CLK_CTL, INPUT)
#define clockOff() pinMode(CLK_CTL, OUTPUT)
#define clockInit() digitalWrite(CLK_CTL, LOW)

void restart_max3949() {

    // note: using MAX3949 datasheet diagram page 8, IMODMAX / SET_IMOD can be
    // set to 200+ but if only AC coupling on the output, care must be taken to avoid
    // excessive voltage swing, otherwise FAULT signal is thrown. hence reduce
    // IMODMAX / SET_IMOD values.

    MAX3949_Write_Register(REG_IMODMAX, IMAX);
    MAX3949_Write_Register(REG_SET_IMOD, IMIN);
    cur_imod = IMIN;

    // biasing not applicable
    MAX3949_Write_Register(REG_IBIASMAX, 0x00);
    MAX3949_Write_Register(REG_SET_IBIAS, 0x00);

    // other tuning parms
    MAX3949_Write_Register(REG_SET_TXEQ, 0x03);

    // start pulser. set MAX3949 register TXCTRL to normal polarity (TX_POL = 1),
    // de-emphasize 9% and transmit active (TX_EN = 1)
    MAX3949_Write_Register(REG_TXCTRL, TXCTRL_VAL);
};

void setup() {

    // init led pin can be change to D13
    pinMode(LED_PIN, OUTPUT);
    ledOff();

    // supress 16MHz signal for a while during setup
    clockOff();
    clockInit();

    // init MAX3949 and Serial for debug
    MAX3949_Init();
    Serial.begin(9600);
    delay(100);

    // release 16MHz signal to circuitry and start max3949 pulser
    restart_max3949();
    clockOn();

    // init elapse timer
    tmr2sta = millis();
};

void blinkLed() {
  byte cur_led_bit = (millis() % LED_RATE) / LED_MODULO;
  if (led_bit & (1 << cur_led_bit)) ledOn();
  else ledOff();
};

// update every 2 seconds
void slow_loop() {
    String str;
    int R05, R06, R07;

    // reading trimpot analog value
    ana1_val = analogRead(ANA1_PIN);            
    ana1_val = map(ana1_val, 0, 1023, 0, ANA1_MAX);
    ana1_val = IMIN + (ana1_val * ((IMAX - IMIN) / ANA1_MAX));

    // set new laser current modulation
    if (ana1_val != cur_imod) {
      cur_imod = ana1_val;
      MAX3949_Write_Register(REG_SET_IMOD, cur_imod);
    };

    // report register value
    str = "Reading Register 0x05 (TXCTRL) = ";
    R05 = MAX3949_Read_Register(REG_TXCTRL);
    str += R05;
    Serial.println(str);

    // report register value
    str = "Reading Register 0x06 (TXSTAT1) = ";
    R06 = MAX3949_Read_Register(REG_TXSTAT1);
    str += R06;
    Serial.println(str);

    // report register value
    str = "Reading Register 0x07 (TXSTAT2) = ";
    R07 = MAX3949_Read_Register(REG_TXSTAT2);
    str += R07;
    Serial.println(str);

    // report trimpot value
    str = "Register 0x09 (SET_IMOD) = ";
    str += ana1_val;
    Serial.println(str);
    Serial.println("");
   
    // check MAX3949 error status (page 24)
    if (digitalRead(FAULT_DETECT) == HIGH) {
      led_bit = 255; // always lit LED. if MAX3949's fault pin is HI (hard fault condition)
    } else if (R06 & 128) { // TXSTAT1, D7
      led_bit = 1; // 1x short blink. Vcc below 2.3V (should be cleared short after startup)
    } else if (R06 & 32) { // TXSTAT1, D5
      led_bit = 5; // twice short blink. no/low (user) AC signal at inputs
    } else if (R06 & 30) { // TXSTAT1, D1-D4
      led_bit = 15; // 1x long led blink. other soft faults (refer to page 24)
    } else if (R07 & 12) { // TXSTAT2, D2-D3
      led_bit = 47; // long + short led blink. soft faults on TXSTAT2
    } else { // all relevant bits cleared
      led_bit = 0; // no fault. pulser should appear on the output
    };

    // check if TXCTRL value is not appropriate (due to arduino reset) TXCTRL_VAL
    if (R05 != TXCTRL_VAL) restart_max3949();
};

void loop() {
    tmr2cur = millis();
    if (tmr2cur < tmr2sta) tmr2sta = tmr2cur;

    if ((tmr2cur - tmr2sta) > ELAPSE2S) {
        slow_loop();
        tmr2sta = tmr2cur;
    };

    // blink led (error) status
    blinkLed();
};
回复 支持 反对

使用道具 举报

     
发表于 2024-7-7 10:37:00 | 显示全部楼层
目前 我读到的REG_TXCTRL  REG_TXSTAT1 REG_TXSTAT2要么0要么255,应该是没有初始化成功,就是没有正确写入,I2C这个注意到了,IO口模拟的三线时序,现在TIN+ TIN-只接了1个,没有用差分时钟,但不影响寄存器的读写,上电后静态电流3mA左右,还在看是不是程序哪个地方有问题,示波器量了#define CSEL_PIN A5
#define SDA_PIN A4
#define SCL_PIN A3
波形是有的
回复 支持 反对

使用道具 举报

     
发表于 2024-7-7 10:39:22 | 显示全部楼层
另外你的电路图上
#define CSEL_PIN A5
#define SDA_PIN A4
#define SCL_PIN A3
没有加上拉电阻,是STM32内部上拉吧,看手册是建议SDA上拉4.7K
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-7 18:52:38 | 显示全部楼层
本帖最后由 scoopydoo 于 2024-7-7 18:54 编辑
maozheng110 发表于 2024-7-7 10:39
另外你的电路图上
#define CSEL_PIN A5
#define SDA_PIN A4


俺的电路里当然是有上拉的,图中的两个 10K 的 R12、R13 就是上拉电阻,STM32 内部只有弱上拉电阻,而且只用于输入模式。

既然你是借鉴的别人已经试验成功的代码,那么出错的地方可能在电路,而不是代码中。

回复 支持 反对

使用道具 举报

     
发表于 2024-7-7 18:55:25 | 显示全部楼层
看错了 不好意思 是CSEL没上拉
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-7 18:56:01 | 显示全部楼层
maozheng110 发表于 2024-7-7 10:13
谢谢,我参考的这个https://www.eevblog.com/forum/beginners/programming-max3949-laser-driver-ic/
max3 ...

贴代码的时候请放在代码块中,你这样贴根本没有办法读的  ......

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2024-7-7 19:00:10 | 显示全部楼层
maozheng110 发表于 2024-7-7 18:55
看错了 不好意思 是CSEL没上拉


CSEL 是片选信号不需要上拉,甚至 MAX49439 的 SCL 也不需要上拉,只有 SDA 需要 4.7K - 10K 的上拉。
回复 支持 反对

使用道具 举报

     
发表于 2024-7-7 20:39:52 | 显示全部楼层
我这边测的 SCL不上拉好像没有波形
回复 支持 反对

使用道具 举报

     
发表于 2024-7-8 08:24:53 | 显示全部楼层
原程序确实有bug
void send_addr(byte addr) 里面需要先加一条,addr <<= 1; 因为地址只有7位;
现在从逻辑分析仪看,是先在0x0E地址里写0x12,再写txctrl
捕获2.JPG
捕获4.JPG
捕获5.JPG
回复 支持 反对

使用道具 举报

     
发表于 2024-7-8 08:26:00 | 显示全部楼层
但TXOUT还是没有,不知道是不是因为输入没有用差分晶振的原因
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-28 14:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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