control 7 TM1637 displays using multiplexer

This commit is contained in:
King Kévin 2017-05-02 17:20:00 +02:00
parent 3bc254fd52
commit 6b80135f67
1 changed files with 104 additions and 12 deletions

116
main.c
View File

@ -65,6 +65,15 @@ volatile uint16_t standby_timer = 0; /**< number of seconds since last wake-up/a
#define FRAME_RATE 25 /**< frame rate */
volatile uint8_t frame_count = 0; /**< number of frames passed */
#define MUX_EN_PORT B
#define MUX_EN_PIN 9
#define MUX_S0_PORT B
#define MUX_S0_PIN 3
#define MUX_S1_PORT B
#define MUX_S1_PIN 4
#define MUX_S2_PORT B
#define MUX_S2_PIN 5
/** user input command */
static char command[32] = {0};
/** user input command index */
@ -174,6 +183,58 @@ error:
return;
}
static void mux_select(uint8_t output)
{
if (output>7) { // multiplexer is only controlling 8 outputs
return;
}
gpio_clear(GPIO(MUX_EN_PORT), GPIO(MUX_EN_PIN)); // enable multiplexer
switch (output) {
case 0: // output on channel C0
gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 1: // output on channel C1
gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 2: // output on channel C2
gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 3: // output on channel C3
gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_clear(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 4: // output on channel C4
gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 5: // output on channel C5
gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_clear(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 6: // output on channel C6
gpio_clear(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
case 7: // output on channel C7
gpio_set(GPIO(MUX_S0_PORT), GPIO(MUX_S0_PIN));
gpio_set(GPIO(MUX_S1_PORT), GPIO(MUX_S1_PIN));
gpio_set(GPIO(MUX_S2_PORT), GPIO(MUX_S2_PIN));
break;
default:
break;
}
}
/** program entry point
* this is the firmware function started by the micro-controller
*/
@ -198,6 +259,7 @@ void main(void)
board_setup(); // setup board
usart_setup(); // setup USART for user communication
cdcacm_setup(); // setup USB ACM (serial) for user communication
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,0); // disable JTAG (but leave SWD on) since we need most of the GPIOs
printf("welcome to the STM32F1 CuVoodoo clapperboard\n"); // print welcome message
#if !(DEBUG)
@ -256,26 +318,45 @@ void main(void)
rtc_ds1307_oscillator_enable(); // enable oscillator again
}
// setup analog multiplexer for TM1637 clock
printf("setup multiplexer: ");
rcc_periph_clock_enable(RCC_GPIO(MUX_EN_PORT));
gpio_set_mode(GPIO(MUX_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_EN_PIN));
gpio_set(GPIO(MUX_EN_PORT), GPIO(MUX_EN_PIN)); // disable multiplexer
rcc_periph_clock_enable(RCC_GPIO(MUX_S0_PORT));
gpio_set_mode(GPIO(MUX_S0_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S0_PIN));
rcc_periph_clock_enable(RCC_GPIO(MUX_S1_PORT));
gpio_set_mode(GPIO(MUX_S1_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S1_PIN));
rcc_periph_clock_enable(RCC_GPIO(MUX_S2_PORT));
gpio_set_mode(GPIO(MUX_S2_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(MUX_S2_PIN));
printf("OK\n");
// setup TM1637 and MAX7219 7-segments displays
printf("setup 7-segment displays: ");
led_tm1637_setup(); // setup TM1637
for (uint8_t tm1637=0; tm1637<7; tm1637++) {
mux_select(tm1637);
if (!led_tm1637_time(88,88)) { // test TM1637 display
printf("could not send time to TM1637 %u\n", tm1637);
}
if (!led_tm1637_on()) { // switch on TM1637 display
printf("could not switch on TM1637 %u\n", tm1637);
}
}
led_max7219_setup(2); // setup MAX7219
if (!led_tm1637_time(88,88)) { // test TM1637 display
printf("could not send time to TM1637\n");
}
if (!led_tm1637_on()) { // switch on TM1637 display
printf("could not switch on TM1637\n");
}
led_max7219_intensity(15,8,0xff); // set brightness max and enable all digits
led_max7219_test(true,0xff); // test all MAX7219 displays
for (uint32_t i=0; i<5000000; i++) { // wait a bit to have the user check the display
__asm__("nop");
}
if (!led_tm1637_text(" ")) { // clear display
printf("could not clear\n");
}
if (!led_tm1637_off()) { // switch off display
printf("could not switch off TM1637\n");
for (uint8_t tm1637=0; tm1637<7; tm1637++) {
mux_select(tm1637);
if (!led_tm1637_text(" ")) { // clear display
printf("could not clear on TM1637 %u\n", tm1637);
}
if (!led_tm1637_off()) { // switch off display
printf("could not switch off TM1637 %u\n", tm1637);
}
}
led_max7219_test(false,0xff); // go back in normal operation
led_max7219_off(0xff); // switch displays off
@ -367,7 +448,7 @@ void main(void)
rtc_tick_flag = false; // reset flag
action = true; // action has been performed
led_toggle(); // toggle LED (good to indicate if main function is stuck)
frame_count = 0; // resync frame counter to second
/*
if (standby_timer>=STANDBY_TIMEOUT) { // standby timeout complete
// go into standby mode
printf("standing by\n");
@ -376,6 +457,7 @@ void main(void)
SCB_SCR |= SCB_SCR_SLEEPDEEP; // enable deep sleep
pwr_set_standby_mode(); // go to deep sleep
}
*/
if (rtc_seconds>=60) { // one minute passed
rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC
if (rtc_ds1307_time==NULL) {
@ -388,6 +470,15 @@ void main(void)
}
}
}
for (uint8_t tm1637=0; tm1637<7; tm1637++) {
mux_select(tm1637);
if (!led_tm1637_time(rtc_ds1307_time[1],rtc_seconds+tm1637)) { // test TM1637 display
printf("could not send time to TM1637 %u\n", tm1637);
}
if (!led_tm1637_on()) { // switch on TM1637 display
printf("could not switch on TM1637 %u\n", tm1637);
}
}
}
while (pwr_get_wakeup_flag()) { // someone is moving the clapperboard
pwr_clear_wakeup_flag(); // clear flag
@ -405,6 +496,7 @@ void main(void)
void EXTI_ISR(SQUARE_WAVE_PIN)(void)
{
exti_reset_request(EXTI(SQUARE_WAVE_PIN)); // reset interrupt
frame_count = 0; // re-sync frame counter to second
rtc_seconds++; // increment number of seconds passed
if (standby_timer<STANDBY_TIMEOUT) { // timeout countdown not complete
standby_timer++; // continue counting down