tm1637: port to STM32F4
This commit is contained in:
parent
5c78aa498e
commit
624006500f
1
global.c
1
global.c
|
@ -262,6 +262,7 @@ void board_setup(void)
|
|||
|
||||
// setup button
|
||||
#if defined(BUTTON_PIN) && defined(BUTTON_PRESSED)
|
||||
rcc_periph_clock_enable(RCC_SYSCFG); // for EXTI port mapping
|
||||
rcc_periph_clock_enable(GPIO_RCC(BUTTON_PIN)); // enable clock for button
|
||||
exti_select_source(GPIO_EXTI(BUTTON_PIN), GPIO_PORT(BUTTON_PIN)); // mask external interrupt of this pin only for this port
|
||||
#if BUTTON_PRESSED // level goes high when pressed
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* @file
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* @date 2017-2020
|
||||
* @date 2017-2022
|
||||
* @note peripherals used: GPIO @ref led_tm1637_gpio, timer @ref led_tm1637_timer
|
||||
* @note the protocol is very similar to I2C but incompatible for the following reasons: the capacitance is too large for open-drain type output with weak pull-up resistors (push-pull needs to be used, preventing to get ACKs since no indication of the ACK timing is provided); the devices doesn't use addresses; the STM32 I2C will switch to receiver mode when the first sent byte (the I2C address) has last bit set to 1 (such as for address commands with B7=1 where B7 is transmitted last), preventing to send further bytes (the data byte after the address)
|
||||
* @warning all calls are blocking
|
||||
|
@ -173,18 +173,20 @@ void led_tm1637_setup(bool updown)
|
|||
// configure GPIO for CLK and DIO signals
|
||||
rcc_periph_clock_enable(GPIO_RCC(LED_TM1637_CLK_PIN)); // enable clock for GPIO peripheral
|
||||
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // idle high
|
||||
gpio_set_mode(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_CLK_PIN)); // master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
|
||||
gpio_set_output_options(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(LED_TM1637_CLK_PIN)); // set pin output as push-pull (capacitance is to large for open drain)
|
||||
gpio_mode_setup(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_CLK_PIN)); // set pin as output, master start the communication
|
||||
rcc_periph_clock_enable(GPIO_RCC(LED_TM1637_DIO_PIN)); // enable clock for GPIO peripheral
|
||||
gpio_set(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_PIN(LED_TM1637_DIO_PIN)); // idle high
|
||||
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
|
||||
gpio_set_output_options(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(LED_TM1637_DIO_PIN)); // set pin output as push-pull (capacitance is to large for open drain)
|
||||
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // set pin as output, only switch to input for ack from slave
|
||||
// first clock then data high also stands for stop condition
|
||||
|
||||
// setup timer to create signal timing (each tick is used for a single GPIO transition)
|
||||
rcc_periph_clock_enable(RCC_TIM(LED_TM1637_TIMER)); // enable clock for timer block
|
||||
rcc_periph_reset_pulse(RST_TIM(LED_TM1637_TIMER)); // reset timer state
|
||||
timer_set_mode(TIM(LED_TM1637_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
|
||||
timer_set_prescaler(TIM(LED_TM1637_TIMER), 0); // don't prescale to get most precise timing ( 1/(72E6/1/(2**16))=0.91 ms > 0.5 us )
|
||||
timer_set_period(TIM(LED_TM1637_TIMER), 500); // set the clock frequency (empirical value until the signal starts to look bad)
|
||||
timer_set_prescaler(TIM(LED_TM1637_TIMER), 0); // don't prescale to get most precise timing ( 1/(72E6/1/(2**16))=0.78 us > 0.5 us )
|
||||
timer_set_period(TIM(LED_TM1637_TIMER), 600); // set the clock frequency (empirical value until the signal starts to look bad)
|
||||
timer_clear_flag(TIM(LED_TM1637_TIMER), TIM_SR_UIF); // clear flag
|
||||
timer_update_on_overflow(TIM(LED_TM1637_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
||||
}
|
||||
|
@ -235,7 +237,7 @@ static bool led_tm1637_write(const uint8_t* data, size_t length)
|
|||
led_tm1637_tick(); // wait for next tick (no DIO transition when CLK is high)
|
||||
gpio_clear(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK low
|
||||
}
|
||||
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO as input to read ACK
|
||||
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO as input to read ACK
|
||||
led_tm1637_tick(); // wait for next tick (when the slave should ACK)
|
||||
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK high
|
||||
if (gpio_get(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_PIN(LED_TM1637_DIO_PIN))) { // no ACK received
|
||||
|
@ -244,11 +246,11 @@ static bool led_tm1637_write(const uint8_t* data, size_t length)
|
|||
}
|
||||
led_tm1637_tick(); // wait for next tick
|
||||
gpio_clear(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK low
|
||||
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO back to output to send next byte
|
||||
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO back to output to send next byte
|
||||
}
|
||||
|
||||
// send stop condition
|
||||
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // ensure DIO is output (in case no ACK as been received
|
||||
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // ensure DIO is output (in case no ACK as been received
|
||||
led_tm1637_tick(); // wait for next tick
|
||||
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK high
|
||||
led_tm1637_tick(); // wait for next tick
|
||||
|
|
Loading…
Reference in New Issue