Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Счетчик импульсов с выводом на 7-ми сегментный индикатор
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Страницы: 1, 2
XVR
Цитата(shadow86 @ Dec 18 2011, 22:45) *
Уважаемые программисты, подскажите, пожалуйста, где мне (и что) добавить, чтоб программа считала импульсы в течение 46с и выдавала на индикатор последнее посчитанное значение,

Для этого вам надо отсчитать 46 секунд. Единственное место у вас, где есть какая то известная периодичность - это динамическое сканирование индикатора (прерывание от таймера), вот в нем и отсчитывайте.
Как насчитаете - копируйте накопленное значение счетчика в переменную, из которой и будете выводить на индикаторы, а счетчик сбрасывайте
Vladex
Цитата(shadow86 @ Dec 7 2011, 00:11) *
чтоб во время счетного периода выводилось последнее посчитанное число импульсов, а не 1, 2, 3, .. и т.д.

буферизуй индикацию регистрами-защелками (ИР24 или им подобными)по окончанию счета, и не надо микроконтроллера будет
shadow86
Попробывал соеденить один из выходов-катодов с еще одной ножкой-входом, чтоб считать изменения уровня на этой ножке и от него отталкиваясь, получить 46с задержки, но что-то опять не получается ((
. . .
PORTA.3 = 0;
DDRA.3 = 0;
PORTA.4 = 0;
DDRA.4 = 0;
ACSR = 0x80;
#asm("sei");
while(1){
while (PINA.3 == 1) {counterProg++;} // регистрирую изменение уровня на входе РА3 (соединенного с одним из зажигаемых катодов индикатора)

while (PINA.4 == 1){} //считаю импульсы
{imp ++;}
while (PINA.4 == 0){}
if (imp >= 1000) {
imp -= 1000;
}
if (counterProg == 10) { //обнуляю количество импульсов
imp = 0;
counterProg = 0;}
IND_Conv(imp); //вывожу количество имп. за счетный период на индикатор

}
toweroff
Да зачем такие извращения?
Один таймер в счетном режиме, на него заводим то, что нужно считать
Второй отсчитывает время. Прошло 46 сек - читаем состояние вервого счетного таймера и обнуляем его
shadow86
вот вам легко говорить... у меня 0-й работает на динамическую индикацию. когда пытаюсь запустить 1-й, то фигня какая-то получается.. либо индикация отказывает, либо счет останавливается.. не могу победить пока что использование 2 счетчиков-таймеров одновременно (((
toweroff
Цитата(shadow86 @ Dec 23 2011, 18:05) *
вот вам легко говорить... у меня 0-й работает на динамическую индикацию. когда пытаюсь запустить 1-й, то фигня какая-то получается.. либо индикация отказывает, либо счет останавливается.. не могу победить пока что использование 2 счетчиков-таймеров одновременно (((

А вот тут нужно смотреть, что там наваяно
Как приоритеты расставлены, как что...

А зачем использовать два таймера для временных интервалов? Тот, который динамическую индикацию осуществляет, вполне посчитает и 46сек...
shadow86
а как это должно выглядеть? у меня вынесена отдельная функция на динамику:
void IND_Update(void)
{
static unsigned char count = 0;

PORT_K &= ~((1<<KAT1)|(1<<KAT2)|(1<<KAT3));
PORT_IND = data[count];
{
if (count == 0) {
PORT_K |= (0<<KAT1);
PORT_K |= (1<<KAT2);
PORT_K |= (1<<KAT3);
}
if (count == 1){
PORT_K |= (0<<KAT2);
PORT_K |= (1<<KAT1);
PORT_K |= (1<<KAT3);
}
if (count == 2) {
PORT_K |= (0<<KAT3);
PORT_K |= (1<<KAT1);
PORT_K |= (1<<KAT2);
}
count++;
if (count == 3) {count = 0;}
}
}
допустим, я могу повышать еще некоторую переменную на ряду с count, а как потом мне ее значение вынести в тело основной программы?
toweroff
да покажите уже полностью, что там наваяли
shadow86
Нажмите для просмотра прикрепленного файлаВот моя программа
Она считает импульсы на РА3 и выводит их количество на 3-х знаковый 7-ми сегментный индикатор.
shadow86
Вот попробывал добавить функцию на счет некоторой переменной.. ПОМОГИТЕ ПОЖАЛУЙСТА!!! У меня уже фантазия иссякла

#include <tiny26.h>

unsigned char number[] =
{
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
};

#define PORT_IND PORTB
#define DDR_IND DDRB
#define PORT_K PORTA
#define DDR_K DDRA
#define KAT1 0
#define KAT2 1
#define KAT3 2

volatile unsigned char data[3];
static unsigned int time;
void IND_Init(void)
{
//порт, к которому подкл. сегменты
PORT_IND = 0xff;
DDR_IND = 0xff;

//порт, к которому подкл. катод
PORT_K &= ~((1<<KAT1)|(1<<KAT2)|(1<<KAT3));
DDR_K |= ((1<<KAT1)|(1<<KAT2)|(1<<KAT3));

data[0] = 0;
data[1] = 0;
data[2] = 0;
}

void IND_Conv(unsigned int value)
{
unsigned char tmp0, tmp1, tmp2;
tmp0=tmp1=0;
while (value >= 100)
{ value -= 100;
tmp0++;
}
while (value >= 10)
{ value -= 10;
tmp1++;
}
tmp2 = value;

data[0]=number[tmp0]; //вывод сотен
data[1]=number[tmp1]; //вывод десятков
data[2]=number[tmp2]; //вывод единиц
}

void IND_Update(void)
{
static unsigned char count = 0;
PORT_K &= ~((1<<KAT1)|(1<<KAT2)|(1<<KAT3));
PORT_IND = data[count];
{
if (count == 0) {
PORT_K |= (0<<KAT1);
PORT_K |= (1<<KAT2);
PORT_K |= (1<<KAT3);
}
if (count == 1){
PORT_K |= (0<<KAT2);
PORT_K |= (1<<KAT1);
PORT_K |= (1<<KAT3);
}
if (count == 2) {
PORT_K |= (0<<KAT3);
PORT_K |= (1<<KAT1);
PORT_K |= (1<<KAT2);
}
count++;
if (count == 3) {count = 0;}
}
}

int Wait (void)
{
time++;
return time;
}
unsigned int imp = 0;
void main( void )
{
IND_Init();

//инициализация таймера Т0
//частота прерываний 50Гц при частоте кварца 4МГц
TIMSK = (1<<TOIE0);
TCCR0 = (1<<CS02)|(0<<CS01)|(1<<CS00);
TCNT0 = 0xb2;
PORTA.3 = 1;
DDRA.3 = 0;

TCCR1A = (1<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);
TCNT1 = 0x00;
#asm("sei");
while(1){
while (PINA.3 == 1){}
{imp ++;}
while (PINA.3 == 0){}
if (imp >= 1000) {
imp -= 1000;
}

IND_Conv(imp);
if (Wait()>=10){
time=0;
imp=0;}
}
}

//прерывания таймера Т0 - вывод на индикатор
interrupt [TIM0_OVF] void Timer0Ovf(void)
{
TCNT0 = 0xb2;
IND_Update();
Wait();
}
Палыч
Поскольку у Вас таймер "тикает" с частотой 50 Гц (верю Вам на слово), то за 49 сек таймер "натикает" 50 * 49 = 2450 раз. Поэтому:
Код
unsigned int t= 0;

//прерывания таймера Т0 - вывод на индикатор
interrupt [TIM0_OVF] void Timer0Ovf(void)
{
  TCNT0 = 0xb2;
  if(++t >= 2450)
  {
    t=0;
    IND_Conv(imp);
    imp= 0;
  }
  IND_Update();
}


Возникает проблема с неатомарностью изменения переменной imp в функции main. Там, где эта переменная изменяется в main - необходимо обрамить командами запрета и разрешения прерывания.

PS. Другое решение: не трогать переменную imp в обработчике прерывания от таймера, а по истечению 49 сек взвести некий флаг, а уж в main этот флаг анализировать, и, по нему вызывать IND_Conv и сбрасывать imp :
Код
unsigned int t= 0;
volatile char flag= 0;

в main
........
  if(flag)
  {
    flag=0;
    IND_Conv(imp);
    imp= 0;
  }
........
//прерывания таймера Т0 - вывод на индикатор
interrupt [TIM0_OVF] void Timer0Ovf(void)
{
  TCNT0 = 0xb2;
  if(++t >= 2450)  {    t=0; flag= 1;  }
  IND_Update();
}
shadow86
Всех с новым годом!!!
Спасибо огромное, Палыч!
muravei
С МК, конечно, пральнее sm.gif , но можно было не париться, сделать: жд. мульт. -интегр. фильтр- измеритель
shadow86
Снова здравствуйте, уважаемые программисты! У меня такой вопрос образовался: если я не хочу применять кварц для тактирования МК, а хочу, чтоб он от внутреннего генератора на 1МГц работал, мне в программе что-либо указывать нужно, или он по умолчанию от него запустится?
XVR
Цитата(shadow86 @ Feb 2 2012, 15:59) *
если я не хочу применять кварц для тактирования МК, а хочу, чтоб он от внутреннего генератора на 1МГц работал, мне в программе что-либо указывать нужно
Вам нужно правильным образом прошить фьюзы при програмировании вашей прошивки

shadow86
спасибо! буду теперь с этим разбираться..
shadow86
Уважаемые форумчане, помогите разобраться с очередным бзиком моего Гейгера. Преобразователь на питание МК из 2.4В в 5В работает идеально: напряжение 5.02В, пульсации не вижу на осциллографе даже при максимальном усилении. На вход МК (РВ4) подаю сформированные подготовленные импульсы с ждущего мультивибратора на к155аг1 (пробовал разные длительности: от 0.1с до 0.1мс), а после заданного промежутка времени и счета на индикатор выводятся какие-то космические значения (как я заметил, кратные 10)!!! которых в принципе быть не может - вместо 11-17 -- 510-820. Как понимать что он считает и как это исправить??? на питании МК стоит 10мк+0.1мк потом дроссель на 10мкГн потом 0.1мк; после преобразователя - 0.1мк+220мк+1500мк. я так понимаю, что по входу идет наводка. как бы ее зашунтировать?
OlegH
Ну так найдите ошибку.... Уменьшите свои 46 секунд до удобного в отладке значения (можно текущее число импульсов сразу выводить на индикацию а не ждать какое-то время) и сымитируйте 1 импульс на счетный вход. Ищите ошибку в программе до тех пор пока поведение не будет адекватным.... Очевидно либо импульс с дребезгом либо программа на один импульс увеличивает счетчик множество раз. А может само число счетчика неправильно формируется для вывода на индикатор (на что косвенно намекает кратность 10)
shadow86
Спасибо за совет, Олег! Попробую так.
shadow86
Спасибо большое за внимание! разобрался! это не наводка была по входу.. а кривые руки.. при изготовлении платы индикатора отзеркалил 1 и 3 разряд, вот у меня 3-х значные числа и лезли ))).
shadow86
А подскажите, пожалуйста, как должен выглядеть текст программы, если я хочу сделать короткий звуковой сигнал с одной из ножек МК, который будет звучать при появлении счетного импульса на входной ножке? Интересует момент формирования звука.
ILYAUL
Цитата(shadow86 @ Mar 25 2012, 21:54) *
А подскажите, пожалуйста, как должен выглядеть текст программы, если я хочу сделать короткий звуковой сигнал с одной из ножек МК, который будет звучать при появлении счетного импульса на входной ножке? Интересует момент формирования звука.


Вам нужно два счётчика . Счетчик- длительности звучания и счётчик -частота звучания. Второе выбирается из DS на пищалку. Длительность на слух.
shadow86
спасибо за ответ! Бум стараться )
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.