Jump to content
    

Zync-7000 SoC. выходы "открытый коллектор"

Если кто работал с Zync-7000, подскажите, пожалуйста. Есть ли у этого зверя возможность сконфигурировать пользовательский выход как "открытый коллектор"? Есть необходимость несколькими оптронами с его помощью управлять.

Edited by T-101

Share this post


Link to post
Share on other sites

2 часа назад, T-101 сказал:

оптронами с его помощью управлять

Для этого совершенно необязательно "открытый коллектор".

Share this post


Link to post
Share on other sites

В выходной регистр пишем 0. Управляем включением выходного буфера.

Edited by GenaSPB

Share this post


Link to post
Share on other sites

15 minutes ago, GenaSPB said:

В выходной регистр пишем 0. Управляем включением выходного буфера.

Спасибо за отклик. Скажите, вы так делали или вы думаете что можно так сделать? Входной ток 10-15 мА буфер потянет? Поймите правильно, мне сейчас на данном этапе разработки с этим нельзя ошибиться.

Share this post


Link to post
Share on other sites

2 hours ago, T-101 said:

Скажите, вы так делали

Spoiler
	// Enable output drive for pin
	#define MIO_SET_TRI_ENABLE(pin, tri_enable) do { \
		if (!(tri_enable)) { SCLR->MIO_PIN [(pin)] &= ~ 0x01; } else { SCLR->MIO_PIN [(pin)] |= 0x01; } \
	} while (0)

	// set pin mode
	// MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable)
	#define gpio_opendrain2(pin, drive, pinmode) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OUTPUTS(bank, mask, 0); \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
			MIO_SET_TRI_ENABLE((pin), ! (drive)); \
		} \
		GPIO_BANK_SET_DIRM(bank, mask, mask); \
		GPIO_BANK_SET_OEN(bank, mask, mask); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	// Enable output drive for pin (thread-safe, for different pins)
	#define gpio_drive(pin, drive) do { \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_TRI_ENABLE((pin), ! (drive)); \
		} \
	} while (0)

	// set pin mode
	// MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable)
	#define emio_opendrain2(pin, drive) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OUTPUTS(bank, mask, 0); \
		GPIO_BANK_SET_DIRM(bank, mask, mask); \
		GPIO_BANK_SET_OEN(bank, mask, mask * !! (drive)); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	// Enable output drive for pin
	#define emio_drive(pin, drive) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OEN(bank, mask, mask * !! (drive)); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	#define gpio_peripherial(pin, pinmode) do { \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
		/*GPIO_BANK_SET_DIRM(bank, mask, mask); */\
		/*GPIO_BANK_SET_OEN(bank, mask, mask); */\
		} \
	} while (0)

 

Как-то так:
 

Spoiler
	// Инициализация битов портов ввода-вывода для аппаратной реализации I2C
	// присоединение выводов к периферийному устройству
	//	mask_write 0XF80007A8 0x00003FFF 0x00001240
	//	mask_write 0XF80007AC 0x00003FFF 0x00001240
	// MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable)
	#define	TWIHARD_INITIALIZE() do { \
		const portholder_t pinmode = MIO_PIN_VALUE(1, 1, TARGET_TWI_IOTYPE, 0, 0x02, 0, 0, 0, 0); \
		gpio_peripherial(TARGET_TWI_TWD_MIO, pinmode);	/*  PS_MIO43_501 SDA */ \
		gpio_peripherial(TARGET_TWI_TWCK_MIO, pinmode);	/*  PS_MIO42_501 SCL */ \
	} while (0)

	#define TWISOFT_INITIALIZE() do { \
		const portholder_t pinmode =  MIO_PIN_VALUE(1, 1, TARGET_TWI_IOTYPE, 0, 0, 0, 0, 0, 0); \
		gpio_opendrain2(TARGET_TWI_TWD_MIO, 0, pinmode);		/*  PS_MIO43_501 SDA */ \
		gpio_opendrain2(TARGET_TWI_TWCK_MIO, 0, pinmode);		/*  PS_MIO42_501 SCL */ \
	} while(0)

	#define SET_TWCK() do { gpio_drive(TARGET_TWI_TWCK_MIO, 0); } while (0)
	#define CLR_TWCK() do { gpio_drive(TARGET_TWI_TWCK_MIO, 1); } while (0)

	#define SET_TWD() do { gpio_drive(TARGET_TWI_TWD_MIO, 0); } while (0)
	#define CLR_TWD() do { gpio_drive(TARGET_TWI_TWD_MIO, 1); } while (0)

	#define GET_TWCK() (gpio_readpin(TARGET_TWI_TWCK_MIO))
	#define GET_TWD() (gpio_readpin(TARGET_TWI_TWD_MIO))

 

 

Всякое, что в  вышеприведённом куске используется
 

Spoiler

	#define ZYNQ_IORW32(addr) (* (volatile uint32_t *) (addr))
	void gpiobank_lock(unsigned bank, IRQL_t * oldIrql);
	void gpiobank_unlock(unsigned bank, IRQL_t oldIrql);

	// ug585-Zynq-7000-TRM.pdf v1.12.2, page 1631

	#define MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable) \
		( \
				((uint_fast32_t) !! (disablercvr) << 13) | /* 1: disable HSTL Input Buffer */ \
				((uint_fast32_t) !! (pullup) << 12) | /* 1: enable Pullup on IO Buffer pin */ \
				((uint_fast32_t) (io_type) << 9) | \
				((uint_fast32_t) !! (speed) << 8) | /* 0: slow CMOS edge */ \
				((uint_fast32_t) (l3_sel) << 5) | \
				((uint_fast32_t) (l2_sel) << 3) | \
				((uint_fast32_t) !! (l1_sel) << 2) | \
				((uint_fast32_t) !! (l0_sel) << 1) | \
				((uint_fast32_t) !! (tri_enable) << 0) | /* Tri-state enable, active high. */ \
				0 \
		)
	/* EMIO сигналы нумеруются начиная с 54 - ZYNQ_MIO_CNT */
	#define GPIO_PINGAP(pin) (((pin) < ZYNQ_MIO_CNT) ? (pin) : ((pin) + (64 - ZYNQ_MIO_CNT)))
	#define GPIO_PIN2BANK(pin) (GPIO_PINGAP(pin) / 32)
	#define GPIO_PIN2BITPOS(pin) (GPIO_PINGAP(pin) % 32)
	#define GPIO_PIN2MASK(pin) ((portholder_t) 1 << GPIO_PIN2BITPOS(pin))

	#define GPIO_BANK_DEFINE(pin, Bank, PinNumber) do { \
		Bank = GPIO_PIN2BANK(pin);    \
		PinNumber = GPIO_PIN2BITPOS(pin); \
	} while(0)

	enum
	{
		GPIO_IOTYPE_LVCMOS18 = 0x01,
		GPIO_IOTYPE_LVCMOS25 = 0x02,
		GPIO_IOTYPE_LVCMOS33 = 0x03,
		GPIO_IOTYPE_HSTL = 0x04
	};
	// initial value = 0x00001601
	#define MIO_SET_MODE(pin, pinmode) do { \
		SCLR->MIO_PIN [(pin)] = (pinmode); /*  */ \
	} while (0)

	// set pin state (thread-safe)
	#define GPIO_BANK_SET_OUTPUTS(bank, mask, outstate) do { \
		const portholder_t maskmsw = ((~ (uint32_t) (mask)) >> 16) & 0xFFFF; \
		const portholder_t masklsw = ((~ (uint32_t) (mask)) >> 0) & 0xFFFF; \
		if (masklsw != 0xFFFF) { \
			const portholder_t datalsw = ((uint32_t) (outstate) >> 0) & 0xFFFF; \
			ZYNQ_IORW32(GPIO_MASK_DATA_LSW(bank)) = (masklsw << 16) | datalsw; \
			(void) ZYNQ_IORW32(GPIO_MASK_DATA_LSW(bank)); \
		} \
		if (maskmsw != 0xFFFF) { \
			const portholder_t datamsw = ((uint32_t) (outstate) >> 16) & 0xFFFF; \
			ZYNQ_IORW32(GPIO_MASK_DATA_MSW(bank)) = (maskmsw << 16) | datamsw; \
			(void) ZYNQ_IORW32(GPIO_MASK_DATA_MSW(bank)); \
		} \
	} while (0)

	//	DIRM: Direction Mode. This controls whether the I/O pin is acting as an input or an output.
	//	Since the input logic is always enabled, this effectively enables/disables the output driver. When
	//	DIRM[x]==0, the output driver is disabled.

	#define GPIO_BANK_SET_DIRM(bank, mask, odstate) do { \
		const uintptr_t dirm = GPIO_DIRM(bank); \
		ZYNQ_IORW32(dirm) = (ZYNQ_IORW32(dirm) & ~ (mask)) | ((mask) & (odstate)); /* Then DIRM[x]==0, the output driver is disabled. */ \
	} while (0)

	//	OEN: Output Enable. When the I/O is configured as an output, this controls whether the output
	//	is enabled or not. When the output is disabled, the pin is 3-stated. When OEN[x]==0, the output
	//	driver is disabled.
	//	Note: If MIO TRI_ENABLE is set to 1, enabling 3-state and disabling the driver, then OEN is
	//	ignored and the output is 3-stated.

	#define GPIO_BANK_SET_OEN(bank, mask, odstate) do { \
		const uintptr_t oen = GPIO_OEN(bank); \
		ZYNQ_IORW32(oen) = (ZYNQ_IORW32(oen) & ~ (mask)) | ((mask) & (odstate)); /* When OEN[x]==0, the output driver is disabled */ \
	} while (0)

	// set pin state (thread-safe)
	#define gpio_writepin(pin, state) do { \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		GPIO_BANK_SET_OUTPUTS(bank, mask, mask * !! (state)); \
	} while (0)

	// set pin mode
	#define gpio_output2(pin, state, pinmode) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
		} \
		GPIO_BANK_SET_OUTPUTS(bank, mask, mask * !! (state)); \
		GPIO_BANK_SET_OEN(bank, mask, mask); \
		GPIO_BANK_SET_DIRM(bank, mask, mask); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	#define gpio_input2(pin, pinmode) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
		} \
		GPIO_BANK_SET_OEN(bank, mask, 0); \
		GPIO_BANK_SET_DIRM(bank, mask, 0); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	void gpio_onchangeinterrupt(unsigned pin, void (* handler)(void * ctx), void * ctx, uint32_t priority, uint32_t tgcpu);
	void gpio_onrisinginterrupt(unsigned pin, void (* handler)(void * ctx), void * ctx, uint32_t priority, uint32_t tgcpu);
	void gpio_onfallinterrupt(unsigned pin, void (* handler)(void * ctx), void * ctx, uint32_t priority, uint32_t tgcpu);

	// Enable output drive for pin
	#define MIO_SET_TRI_ENABLE(pin, tri_enable) do { \
		if (!(tri_enable)) { SCLR->MIO_PIN [(pin)] &= ~ 0x01; } else { SCLR->MIO_PIN [(pin)] |= 0x01; } \
	} while (0)

	// set pin mode
	// MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable)
	#define gpio_opendrain2(pin, drive, pinmode) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OUTPUTS(bank, mask, 0); \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
			MIO_SET_TRI_ENABLE((pin), ! (drive)); \
		} \
		GPIO_BANK_SET_DIRM(bank, mask, mask); \
		GPIO_BANK_SET_OEN(bank, mask, mask); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	// Enable output drive for pin (thread-safe, for different pins)
	#define gpio_drive(pin, drive) do { \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_TRI_ENABLE((pin), ! (drive)); \
		} \
	} while (0)

	// set pin mode
	// MIO_PIN_VALUE(disablercvr, pullup, io_type, speed, l3_sel, l2_sel, l1_sel, l0_sel, tri_enable)
	#define emio_opendrain2(pin, drive) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OUTPUTS(bank, mask, 0); \
		GPIO_BANK_SET_DIRM(bank, mask, mask); \
		GPIO_BANK_SET_OEN(bank, mask, mask * !! (drive)); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	// Enable output drive for pin
	#define emio_drive(pin, drive) do { \
		IRQL_t irql; \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		gpiobank_lock(bank, & irql); \
		GPIO_BANK_SET_OEN(bank, mask, mask * !! (drive)); \
		gpiobank_unlock(bank, irql); \
	} while (0)

	#define gpio_peripherial(pin, pinmode) do { \
		const portholder_t bank = GPIO_PIN2BANK(pin); \
		const portholder_t mask = GPIO_PIN2MASK(pin); \
		SCLR->SLCR_UNLOCK = 0x0000DF0DuL; \
		if ((pin) < ZYNQ_MIO_CNT) { \
			MIO_SET_MODE((pin), (pinmode)); /* initial value - with pull-up, TRI_ENABLE=0, then 3-state is controlled by the gpio.OEN_x register. */ \
		/*GPIO_BANK_SET_DIRM(bank, mask, mask); */\
		/*GPIO_BANK_SET_OEN(bank, mask, mask); */\
		} \
	} while (0)

	#define gpio_readpin(pin) ((ZYNQ_IORW32(GPIO_DATA_RO(GPIO_PIN2BANK(pin))) & GPIO_PIN2MASK(pin)) != 0)

 

Проект где всё это - в github находится...

Edited by GenaSPB

Share this post


Link to post
Share on other sites

18 hours ago, T-101 said:

Если кто работал с Zync-7000, подскажите, пожалуйста. Есть ли у этого зверя возможность сконфигурировать пользовательский выход как "открытый коллектор"? Есть необходимость несколькими оптронами с его помощью управлять.

 

Неправильно задан вопрос. Должен быть такой:
Сможет выход сделать лог."0" при токе 15 mA ?

Share this post


Link to post
Share on other sites

20 часов назад, blackfin сказал:

См: DS187, page 11.

Да тут без поллитры не разобраться, то ли дело в АВРках было - все пини держат по 20мА и точка)))

image.thumb.png.cf6a5f345cec0bb71814879b6b9ae11e.png

Share this post


Link to post
Share on other sites

В 05.12.2025 в 15:14, T-101 сказал:

Если кто работал с Zync-7000, подскажите, пожалуйста. Есть ли у этого зверя возможность сконфигурировать пользовательский выход как "открытый коллектор"? Есть необходимость несколькими оптронами с его помощью управлять.

 

Вряд ли у него есть открытый сток.

Можно с имитировать открытый сток на выходном буфере с третьим состоянием. А у него будут парАметры типа:

OBUFT  //=== UG953
    #(
      .DRIVE        (12), // Specify the output drive strength
      .IOSTANDARD   ("DEFAULT"), // Specify the output I/O standard
      .SLEW         ("SLOW") // Specify the output slew rate
     )

IOSTANDARD ПО УМОЛЧАНИЮ - 1.8в. Как то все скользко.

Share this post


Link to post
Share on other sites

1 час назад, sazh сказал:

Как-то все скользко.

Как задача ставится, такое решение и получается.

Давно бы поставил перед своим оптроном копеечный полевичок в SOT-23 с logic-level входом, и не надо было бы устраивать пляски с бубном вокруг контроллера, требовать от него мощного выхода и "открытого коллектора".

Share this post


Link to post
Share on other sites

1 hour ago, r_dot said:

Как задача ставится, такое решение и получается.

Давно бы поставил перед своим оптроном копеечный полевичок в SOT-23 с logic-level входом, и не надо было бы устраивать пляски с бубном вокруг контроллера, требовать от него мощного выхода и "открытого коллектора".

Конечно, так все и поступают.

Edited by whoami

Share this post


Link to post
Share on other sites

On 12/6/2025 at 5:33 PM, r_dot said:

Давно бы поставил перед своим оптроном копеечный полевичок в SOT-23 с logic-level входом, и не надо было бы устраивать пляски с бубном вокруг контроллера, требовать от него мощного выхода и "открытого коллектора".

Запасной вариант у меня был именно такой. Но места на плате очень мало, поэтому хотел обойтись без этого. Но, как я понимаю, не удастся. Большое спасибо всем отвечавшим.

Share this post


Link to post
Share on other sites

6 часов назад, T-101 сказал:

места на плате очень мало

Если у вас на плате аж оптрон, то размер платы - это точно не основное требование.
А если всё-таки основное - примените двусторонний монтаж. Под оптроном SOT-23 встанет со свистом.
Если всё равно не умещается - надо работать в сторону сокращения размера хотелки. :this:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...