Jump to content
Vitaliy129

Динамическая Индикация

Recommended Posts

Всем добрый вечер. Проблема следующая. Есть плата STM32VL Discovery. К ней цепляется з-х разрядный семисегментный индикатор. Цифры предполагается выводить динамически. Но при выводе первого разряда вместе с ним подсвечивается и второй, при выводе 2-го подсвечивается 3-й и соответственно при выводе 3-го подсвечивается 1-й. Пробовал различные частоты вывода и применять задержки между выключением предыдущего индикатора и включением последующего. В чём может быть дело??? На Си только начинаю программировать, поэтому код скорее всего не эффективный, но всё же.

Жду ваших ответов.


#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#define IND_PORT GPIOA// This port is responsible for the display of "IND_PORT"
#define D1 GPIO_Pin_0//This conclusion is responsible for 1st indicator
#define D2 GPIO_Pin_1//This conclusion is responsible for 2nd indicator
#define D3 GPIO_Pin_2//This conclusion is responsible for 3rd indicator
// A segment of the indicator - the output of the microcontroller
#define SEG_A GPIO_Pin_0// seg "A"
#define SEG_B GPIO_Pin_1// seg "B"
#define SEG_C GPIO_Pin_2// seg "C"
#define SEG_D GPIO_Pin_3// seg "D"
#define SEG_E GPIO_Pin_4// seg "E"
#define SEG_F GPIO_Pin_5// seg "F"
#define SEG_G GPIO_Pin_6// seg "G"
#define DP GPIO_Pin_7   //Decimal point
// Create the numbers of segments
#define DIG0 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F )
#define DIG1 ( SEG_B | SEG_C )
#define DIG2 ( SEG_A | SEG_B | SEG_G | SEG_E | SEG_D )
#define DIG3 ( SEG_A | SEG_B | SEG_G | SEG_C | SEG_D )
#define DIG4 ( SEG_F | SEG_G | SEG_B | SEG_C)
#define DIG5 ( SEG_A | SEG_F | SEG_G | SEG_C | SEG_D )
#define DIG6 ( SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G )
#define DIG7 ( SEG_A | SEG_B | SEG_C )
#define DIG8 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define DIG9 ( SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G)
#define ALL_PINS (DIG8 | D1 | D2 | D3 )

// Delay
void Delay (void);
void Delay (void)
{
 unsigned long i;
 for (i=0; i<20000; i++);
}
//


#define TIMER_PRESCALER 720
uint8_t previousState;
uint8_t IND_State;
GPIO_InitTypeDef port;//???
TIM_TimeBaseInitTypeDef timer;
uint8_t counter1;
uint8_t counter2;
uint8_t counter3;
uint8_t rez;
uint8_t digit;

void digit_to_port (uint8_t digit){
uint8_t digitsp[]={DIG0,DIG1,DIG2,DIG3,DIG4,DIG5,DIG6,DIG7,DIG8,DIG9};
IND_PORT->ODR &= ~DIG8;
IND_PORT->ODR |= digitsp[digit];
}
//

void initAll()
{
 GPIO_InitTypeDef port;//???
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //On port "A"
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //On port "B"
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //On timer "Tim 4"

 GPIO_StructInit(&port);
//Port "A" input
   port.GPIO_Mode = GPIO_Mode_Out_PP;  
   port.GPIO_Pin = DIG8 | DP; 
   port.GPIO_Speed = GPIO_Speed_2MHz;  
   GPIO_Init(GPIOA, &port);

//Port "B" output
 port.GPIO_Mode = GPIO_Mode_Out_PP;
 port.GPIO_Pin =D1 | D2 | D3;
 port.GPIO_Speed = GPIO_Speed_2MHz; 
 GPIO_Init(GPIOB, &port); 
// Timer
 TIM_TimeBaseStructInit(&timer);
   timer.TIM_Prescaler = TIMER_PRESCALER;
   timer.TIM_Period = 5000;
   TIM_TimeBaseInit(TIM4, &timer);
}

//
int main()
{
   __enable_irq();
   initAll();
   TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
   TIM_Cmd(TIM4, ENABLE);
   NVIC_EnableIRQ(TIM4_IRQn);
 IND_State=1;
 counter1=1;
 counter2=2;
 counter3=7;
   while(1)
   {
__NOP();
   } 
}
//


void TIM4_IRQHandler()
{

   if (IND_State == 1)
   {
  GPIO_ResetBits(GPIOB, D1|D2|D3);
  GPIO_ResetBits(GPIOA,  DIG8);
  Delay();
  IND_State=2;

  GPIO_SetBits(GPIOB, D1);

  digit_to_port(counter1);
  timer.TIM_Period = 50000;
  TIM_TimeBaseInit(TIM4, &timer);
  TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
 }
 else
 {
  if (IND_State == 2)
  {
  GPIO_ResetBits(GPIOB,  D1|D2|D3);
  GPIO_ResetBits(GPIOA,  DIG8);
  Delay();
  IND_State=3;
  GPIO_SetBits(GPIOB, D2);

  digit_to_port(counter2);
  timer.TIM_Period = 50000;
  TIM_TimeBaseInit(TIM4, &timer);
  TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
  }
  else
  {
  GPIO_ResetBits(GPIOB,  D1|D2|D3);
  GPIO_ResetBits(GPIOA,  DIG8);
  Delay();
  IND_State=1;
  GPIO_SetBits(GPIOB, D3);

  digit_to_port(counter3);
  timer.TIM_Period = 50000;
  TIM_TimeBaseInit(TIM4, &timer);
  TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
  }
 }
}  

Share this post


Link to post
Share on other sites

В код не вникал, но подобная проблема у меня была с СД матрицей 8х8. Попробуй так:

1. Гасим все разряды

2. Устанавливаем значение порта А (сегменты)

3. Включаем нужный пин порта В (разряд индикатора)

4. Пауза

5. Переход в п.1

Share this post


Link to post
Share on other sites

Вебинар «Решения Analog Devices для гальванической изоляции. Обзор технологий и новинок» (27.04.2021)

Компания «Компэл» и Analog Devices приглашают всех желающих 27/04/2021 принять участие в вебинаре, посвященном решениям Analog Devices для гальванической изоляции. В программе вебинара: технологии гальванической изоляции iCoupler, цифровые изоляторы, изолированное питание и технология isoPower, гальванически изолированные интерфейсы (RS-485, CAN, USB, I2C, LVDS) и другое.

Подробнее

Ключевой пункт в предложенном мной алгоритме-№1, т.е. гашение индикаторов, в коде я этого не увидел.

Share this post


Link to post
Share on other sites

Пружинные клеммники Degson - высокое качество соединения по оптимальной цене!

Пружинные клеммные блоки Degson для монтажа на печатную плату – это простое и надежное соединение, которое позволяет легко решать задачи для различных приложений за счет обширного ассортимента. Клеммники Degson доступны в двух конструктивных исполнениях (торцевой контакт и зажимная клеть), имеют различные направления ввода проводника (45°, 90°, 180°) и обладают широким диапазоном поперечных сечений (0,2…2,5 мм2).

Подробнее

GPIO_ResetBits(GPIOB, D1|D2|D3) каждый раз перед загрузкой числа я гашу все разряды,3 а потом включаю нужный

Share this post


Link to post
Share on other sites

Новое семейство ИП от MEAN WELL мощностью 150, 300, 600 Вт с повышенной перегрузочной способностью

Компания MEAN WELL разработала семейство источников питания номинальной мощностью 150, 300 и 600 Вт с возможностью кратковременной безопасной работы при мощности в 2,5 раза выше номинальной (до 5 секунд). Данное семейство источников питания востребовано в промышленных установках с использованием электродвигателей или с емкостной нагрузкой. Применяя новые источники питания HRP/N можно получить экономический выигрыш.

Подробнее

Включайте пошаговый режим и смотрите, где что на что налетает.

Покажите схему, по которой работаете.

Share this post


Link to post
Share on other sites

Эта схема с атмегой 32отлично работала, ошибка чисто программная

post-136109-0-81238500-1372361217_thumb.png

Edited by Vitaliy129

Share this post


Link to post
Share on other sites

Так попробуй:

GPIO_ResetBits(GPIOB, D1|D2|D3);
GPIO_ResetBits(GPIOA, DIG8);
GPIO_SetBits(GPIOB, D2);
Delay();
IND_State=3;

ПС Зачем куча "ифов", используй switch или что там в вашей среде типа select case?

ПСПС Дин.индикацию обычно организуют, используя прерывания по таймеру.

Edited by КЭС

Share this post


Link to post
Share on other sites

"Дин.индикацию обычно организуют, используя прерывания по таймеру." Она и организована по прерыванию от таймера. Функция Delay() введена для попытки сделать небольшое "мёртвое" время между переключениями., По поводу "if" я только начинаю программировать и не сильно знаком с СИ и этим МК.

Edited by Vitaliy129

Share this post


Link to post
Share on other sites

GPIO_ResetBits(GPIOB, D1|D2|D3); достаточно поставить один раз, в начале прерывания, до проверки такта.

GPIO_ResetBits(GPIOA, DIG8); вообще необязательно, достаточно сменить значение на новое (без предварительного обнуления)

А уже после проверки такта выставить GPIO_SetBits(GPIOB, D3);

Share this post


Link to post
Share on other sites

Я вот сегодня , 5 минут назад запустил 3 разрядный индикатор от СТМки : )) Счастья то сколько! А функция писалась еще для ПИКа.

Прикрепляю работающий проект под STM32F051R8

Также куски кода:

void led_out (){

clear_leds; // digit off

switch (y) // select digit
{

case 0:

IND_PORT->ODR = led_buff[0];
digit_1;
break;
case 1:

IND_PORT->ODR = led_buff[1];
digit_2;
break;

case 2:

IND_PORT->ODR = led_buff[2];
digit_3;
break;

}
if (++y>2)y=0;
}

Функция для вывода в порт данных из массива

void indication_func()
{


temp1 = temp;

temp_lcd1=temp_lcd2=temp_lcd3=0;
while (temp1>99)
{
temp1-=100;
temp_lcd3++;
}

while (temp1>9)
{
temp1-=10;
temp_lcd2++;
}

while (temp1<10 && temp1!=0)
{
temp1--;
temp_lcd1++;
}

if(temp<10)
{
led_buff[2]=led_table[temp_lcd1];
led_buff[1]=led_table[10];
led_buff[0]=led_table[10];
}
else if(temp>9 && temp<100)
{
led_buff[1]=led_table[temp_lcd1];
led_buff[2]=led_table[temp_lcd2];
led_buff[0]=led_table[10];
}
else if(temp>99)
{
led_buff[0]=led_table[temp_lcd1];
led_buff[1]=led_table[temp_lcd2];
led_buff[2]=led_table[temp_lcd3];
}

led_out();
}

Функция разложения числа на разряды

Delay(1);
indication_func();
if(timer>5){temp++; timer=0;}
timer++;

Просто крутим по кругу переменную

Код крутится в вечном цикле (просто тестировал, учился, игрался) но его очень легко закинуть в прерывания системного таймера, или любого другого.

Теперь точно буду перелазить на STM32!!!

обучение STM32F051R8.rar


Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  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.

Loading...

×
×
  • Create New...