Перейти к содержанию

crazz

Рекомендуемые сообщения

Начинать нужно с архитектуры решения.

1. Источник секундных событий(импульсов).

2. Интерфейс вывода.

3. Интерфейс управления.

1. Можно делить до секунды аппаратно-программно системный таймер МК. Можно повесить кварц 32768 Гц на LP-генератор первого таймера, а системный генератор сделать встроенным (internal RC 4(8) MHz). Если подойти к задаче формально, то за 10 секунд никакой генератор уйти заметно не сможет - даже RC). Но если принять решение как типовое учебное, то нужно делать корректно, как для больших времен отсчета. Причем с энергоэкономией (слипом между секундными переключениями).

2. Вывод для одной цифры прост. Переменная на индикацию одноразрядная (в десятичной системе). Поэтому нужен только сегментный дешифратор при выводе на пины. Такой дешифратор пишут с помощью табличной конвертации:

.............
;<тут в аккумуляторе число на индикацию>
           call       tab
;<а тут уже сегментный код этого числа>
;<и его можно выводить на пины>

.............
.............
tab        addwf     PCL, f
          retlw     b'xxxxxxxx'   ; "0"
          retlw     b'xxxxxxxx'   ; "1"
          retlw     b'xxxxxxxx'   ; "2"
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'
          retlw     b'xxxxxxxx'   ; "9"

Крестики в бинарном коде таблицы - это конфигурация горящих и не горящих сегментов цифр. Верхняя retlw - это сегментный код нуля, а нижняя соответственно девятки.

3. Интерфейс управления - это кнопка пуска. Для описанной задачи это может быть кнопка на внешнем прерывании или на пине, который может генерировать прерывание по изменению состояния. Требуется обеспечить защиту от повторных пусков при дребезге кнопки по нажатию и , что гораздо важнее, по отпусканию.

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

Тогда и писать алгоритм.

Изменено пользователем my504

戦う前に相手のベルトの色に注目

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

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

Есть в программе прерывания от TMR0, с моим кварцем это 65мс.

Вот значит наступает счет до 10 сек, далее надо я так полагаю, загрузить цифру в порт из таблицы, потом отсчитать одну секунду, потом следующую и в это время проверять кнопку.

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Вы пишете не о том.

Представьте, что Вам дали коробочку с кнопкой и индикатором. Что внутри Вы не знаете, но нужно написать инструкцию пользователя. Вот и напишите об этом, что жать для пуска-сброса, куда смотреть, что там на индикаторе до пуска, что после останова ну и т.д.

А писать как чего там внутри действует - это потом.

戦う前に相手のベルトの色に注目

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Меня интересует где в коде, который я набрал (в конфигурации) ошибка, из-за которой не работает прерывание с низким приоритетом. Подскажите......
Я же Вам показал ошибку в программе.

INTCON2bits.TMR0IP=1;   //встановити пріоритет переривань від TMR0 низьким

Низкий это - 0, высокий - 1.

Ссылка на комментарий
Поделиться на другие сайты

Марк, просто я алгоритм уже описывал здесь. Есть сигнализация с кнопкои снятия постановки и датчиком движения, включаем питание - ничего не происходит, потом нажатием на кнопку ставим на охрану -10 сек ждем для выхода из помещения , вот их и надо индицировать. Потом смотрим на датчик, при срабатывании опять отсчитываем 10 сек, в это время опрашиваем кнопку на отмену ( здесь тоже индикация нужна), если отмены тревоги не было, то соответсвенно тревога.

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

В таком раскладе требуется только семь свободных выходов МК. И вставка в код которую я уже привел.

Как секунда прошла, так и выводите новое значение программного счетчика секунд через эту таблицу.

Если таймер дает переполнения каждые 65, 536 мс , то секунда - это 15 с четвертью переполнений.

Ошибка неприлично велика, поэтому я бы сократил период переполнений таймера (уменьшением коэффициента деления предделителя до 1:64 - это 16,384 мс) и тогда секунда - это 61,04 переполнения таймера (при 61 ошибка=0,07%).

Значит в прерывании по TMR0 организуете программный счетчик до 61 (инкрементируете переменную этого счетчика, а при его значении 61 сбрасываете эту переменную и декрементируете переменную секунд).

Примечание. Ессно, что требуется две однобайтных переменных (счетчика делителя на 61 и собственно переменная секунд).

Вот эту переменную секунд после каждого ее изменения и выводите. Можно даже прямо в том же прерывании (там всего пяток машциклов требуется).

戦う前に相手のベルトの色に注目

Ссылка на комментарий
Поделиться на другие сайты

инкрементируете переменную этого счетчика, а при его значении 61 сбрасываете эту переменную и декрементируете переменную секунд).
А почему нельзя декрнементировать, я всегда декрементировал потомучто проверял на 0, а как я узнаю что уже равно 61? У меня напрашивается ответ что надо от результата инкремента отнять 61 и проверить на ноль, но кажется это не так:)

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

Но все-таки, для общего образования, как узнать что уже 61? Так как я подумал или есть более практичный способ?

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

Но тем не менее, проверка на значение проиводится вычитанием. есть даже специальная команда, которая не меняет операнды но устанавливает флаги регистра состояния будто вычитание было произведено. Эта команда называется командой сравнения - в ассемблере чаще всего пишется как CP или CMP.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Если нужно узнать больше число или равно (>=), то вычитанием и проверкой соответствующего флага.

Если нужно сравнить с числом, тогда исключающее или. 2 одинаковых числа при XOR всегда дадут нулевой результат.

Ссылка на комментарий
Поделиться на другие сайты

Но операция XOR в отличие от CP портит значение регистра - нужны дополнительные движения для восстановления этого значения, если оно будет необходимо после проверки. CP все-таки практичнее. или если точнее - CPI - сравнение с константой.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

портит значение регистра
Результат можно укладывать как в текущий регистр, так и в аккумулятор, что не влияет на результат флагов. Причём XOR с константой можно выполнить только с аккумулятором, так что ничего страшного что он испортится :)
CP все-таки практичнее. или если точнее - CPI - сравнение с константой.
В системе PIC-овых команд, к сожалению, нет команды сранения, по этому приходится извиваться :)
Ссылка на комментарий
Поделиться на другие сайты

Там все происходит через аккумулятор, так и так что-то все равно надо загружать либо в аккумулятор либо в регистр, поэтому не стали вводить дополнительную команду.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Да, все команды с XOR только через аккумулятор. Результат команды XOR регистра и аккумулятора можно оставить в аккумуляторе.

Алгоритм будет такой:

Загрузили сравниваемое число в аккумулятор (movlw .61)

Сделали XOR аккумулятора с регистром, результат в W (xorwf _reg,W)

Проверили флаг нулевого результата (btfsc STATUS,Z)

Ссылка на комментарий
Поделиться на другие сайты

Два варианта:

1. Инкремент:

      incf   count, f
       movlw    .61+1
       xorwf   count, w
       btfsc  STATUS, Z
       clrf   count

2. Декремент:

     decfsz   count, f
      goto   $+3
      movlw  .61+1
      movwf   count

Разница в один машцикл. Непринципиально.

戦う前に相手のベルトの色に注目

Ссылка на комментарий
Поделиться на другие сайты

Меня интересует где в коде, который я набрал (в конфигурации) ошибка, из-за которой не работает прерывание с низким приоритетом. Подскажите......
Я же Вам показал ошибку в программе.

INTCON2bits.TMR0IP=1;   //встановити пріоритет переривань від TMR0 низьким

Низкий это - 0, высокий - 1.

Спасибо за помощь, с этим я уже разобрался...

Но никак не могу заставить выводить число на индикатор при нажатии кнопки:(

Подскажите как.

Или, если не трудно, напишите мне краткий код (типа алгоритма с краткими объяснениями), где это все делается, а то я все никак не могу это сделать.:(

Ссылка на комментарий
Поделиться на другие сайты

Проверяешь нажата ли кнопка - выводишь число в порт(а какое?), если не нажата - отключаешь вывод.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Пожалуйста, изучай. Только компилятор другой (HI-TECH), но принцип думаю будет понятен.

Схема:

post-48853-0-35867300-1289861330_thumb.jpg

При нажатии на кнопку индикаторы сдвигаются влево, а в 4-ый индикатор записвается число соответствующее нажатой кнопки. Кнопки * и # выводят пробел.

Архив с исходником и файлом протеуса

7-seg&keyboard.rar

Для тех, кому лень качать архив:

#include	"pic18.h"
#include	"delay.h"

__CONFIG(1, 0x02FF);	
__CONFIG(2, 0x0EFF);		
__CONFIG(4, 0xFF80);



void keyboard(void);
void key_press(char key_num);



unsigned char const digit[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00};// Сегменты (цифры) 0 1 2 3 4 5 6 7 8 9 
unsigned char buf_ind[4]; // Буфер индикаторов
const char key_val[12] = {1,2,3,4,5,6,7,8,9,10,0,10};	// Коды кнопок
char buf_key[10];	// Буфер номеров нажатых кнопок
char key_flag=0;	// Флаг/счётчик нажатых кнопок. Показатель того, нажата ли кнопка и сколько их нажато до обработки




//******************************************************//
void main()
{
char tmp,i;	// Временные переменные

TRISC=0b10000000;
PORTC=0xFF;
TRISD=0b11110000;
PORTD=0xF0;
TRISB=0b11100001;
PORTB=0b00011110;

key_flag=0;


TMR1ON=1;	// Вкл. таймер 1
TMR1IF=0;	// Сбросили флаг
TMR1IE=1;	// Разрешили прерывание от TMR1
TMR1 = 65536-2500;	// Установили значение таймера на 2500 циклов


PEIE=1;
GIE=1;

//--Очищаем индикаторы--//
buf_ind[0] = ~digit[10];
buf_ind[1] = ~digit[10];
buf_ind[2] = ~digit[10];
buf_ind[3] = ~digit[10];  
//---------------------//


while(1)	// Основной цикл
{

//----- Задержка 1 сек. -------//
DelayMs(250);DelayMs(250);	
DelayMs(250);DelayMs(250);
//-----------------------------//

//---- Обрабатываем нажатые кнопки (если нажатия были) ---------//
while(key_flag){	// Пока счётчик >0
	tmp=buf_key[0]; 	// Сохраняем номер первой необработанной нажатой кнопки
	GIE=0;				// Запрещаем прерывания. ОБЯЗАТЕЛЬНО !!!!
		for(i=0;i<9;i++){	// Двигаем буфер номеров влево
			buf_key[i] = buf_key[i+1];
		}
	key_flag--;		// Счётчик нажатых кнопок -1
	GIE=1;			// Разрешаем прерывания

	key_press(tmp);	// Вызываем процедуру обработки нажатой кнопки
}	// и так все нажатия до последнего
//---------------------------------------------------------------//

}
}
//******************************************************//

//******************************************************//
void key_press(char key_num)	// Обработчик нажатой кнопки. key_num - номер нажатой кнопки
{
char i,cod;

for(i=0;i<3;i++){	// Двигаем буфер индикаторов влево
	buf_ind[i] = buf_ind[i+1];
}
cod = key_val[key_num];		// Выдираем код нажатой кнопки из таблицы
buf_ind[3] = ~digit[cod];	// В 4-ый индикатор пихаем код

}
//******************************************************//

//***** обработчик прерываний ***********************//
void interrupt _isr(void)
{
static unsigned char ind_num=0;	// Номер индикатора
static char cnt_ms=10;			// Счётчик mS для опроса кнопок


if(TMR1IF)	// Проверяем флаг
{
	TMR1IF=0;	// Сбрасываем флаг
	TMR1 = 65537-2500 + TMR1;	// Переустанавливаем таймер на 1 mS

	ind_num++;	// Следующий индикатор
	if(ind_num>3)	ind_num=0;	// Если зашкалило, выбираем первый

	PORTD &=0b11110000;	// Гасим индикаторы
	NOP();NOP();NOP();NOP();NOP();	// Небольшая задержка
	PORTC=buf_ind[ind_num];			// Выводим в порт значение текущего индикатора из буфера
	PORTD |=(1<<ind_num);			// Зажигаем текущий индикатор


	if(!--cnt_ms){	// Отсчитываем 10 mS
		cnt_ms=10;
		keyboard();	// Вызываем процедуру опроса кнопок
	}
}
}
//***************************************************//

//***************************************************//
void keyboard()
{
char i;
static char H_num=0;		// Номер опрашиваемой строки
char key_num;				// Порядковый номер опрашиваемой кнопки
char key_par[12];			// Текущие состояния кнопок
static char key_tmp[12];	// Предыдущие состояния кнопок


H_num++;		// Следующая строка
if(H_num>3){	// Если зашкалило - выбираем первую строку
H_num=0;
}
key_num =H_num*3;	// Смещаем номер опрашиваемой кнопки относительно номера строки


RB1=1;RB2=1;RB3=1;RB4=1;	// На всех строках 1-чки

if(H_num==0)	RB4=0;		// 0 на 1-й строке
if(H_num==1)	RB3=0;		// 0 на 2-й строке
if(H_num==2)	RB2=0;		// 0 на 3-й строке
if(H_num==3)	RB1=0;		// 0 на 4-й строке


if(!RB5)				// Если в 1-ом стобце лог.0
key_par[key_num]=1; // текущее состояние кнопки - нажато
else					// иначе
key_par[key_num]=0;	// cостояние - отжато

key_num++;	// Номер кнопки +1
if(!RB6)
key_par[key_num]=1;
else
key_par[key_num]=0;

key_num++;	// Номер кнопки +1
if(!RB7)
key_par[key_num]=1;
else
key_par[key_num]=0;


//---- Сохраняем текущие состояния кнопок ----//
//---- и смотрим изменения состояний ---------//
for(i=0;i<12;i++){		
if(key_tmp[i] && !key_par[i]) {	// Если предыдущее состояние было нажато и текущее отжато
	buf_key[key_flag] = i;		// Сохраняем в буфер номер нажатой кнопки
	key_flag++;					// Увеличиваем флаг/счётчик на 1
}
key_tmp[i] = key_par[i];	// Сохраняем текущие состояния
}
//-------------------------------------------//


}

Прошу обратить внимание на задержку 1 сек. в основном цикле, после которой обрабатываются нажатые кнопки.

Сделал её я не зря. Пример показывает как можно реализовать буфер нажатых кнопок для последующей обработки. Т.е. нажатия на кнопки укладываюся в некий буфер, точнее укладываются номера нажатых кнопок. Если во время этой задержки нажать несколько кнопок подряд, то по истечению задержки, нажатия все обработаются без потерь.

Вобщем юзай, изучай, спрашивай...

PS: Это мой первый опыт в опросе дин. клавы, так что критика приветствуется :)

Ссылка на комментарий
Поделиться на другие сайты

Написал для индикации 10 секунд следующее:

Значить в превывании от TMR0 декрементирую регистр с переменнои SecL

Otschet  bsf         STATUS,5
        clrf        OPTION_REG
        movlw       b'10000101'  ; TMR0 1:64 (16,384ms)
        movwf       OPTION_REG
        bcf         STATUS,5
        movlw       .9
        movwf       Secund       ; количество секунд
loop     movlw       .61
        movwf       SecL         ; Переменная однои секунды.
        bsf         Flag,0       ; Начнем отсчет( сбросится в прерывании когда досчитает)
        movf        Secund       ; Загрузим, то что будем показывать.
Indic    call        TABLE        ; Загружаем на индикацию
        movwf       PORTB
        btfsc       Flag,0       ; Секунда прошла?
        goto        Indic        ; Если нет, то повторим индикацию
        xorlw       b'00111111'  ; Если прошла, то проверим вытолкнули ли 0?
        btfss       STATUS,2     ; Если в W был 00111111, то флаг поднимется
        goto        OGID         ; Если поднялся, то больше здесь делать нечего - на ОХРАНУ
        decf        Secund,1     ; декрементируем Секунды, сохраняем в регистре
        goto        loop         ; Повторим.

TABLE      addwf       PC,F        ; Содержимое счетчика команд PC увеличивается
                                   ; на величину содержимого аккумулятора W.
           retlw       b'00111111' ; ..FEDCBA = 0              Происходит скачек по таблице
           retlw       b'00000110' ; .....CB. = 1               на строку со значением, 
           retlw       b'01011011' ; .G.ED.BA = 2               записанным в аккумуляторе,
           retlw       b'01001111' ; .G..DCBA = 3               и далее - возврат по стеку.
           retlw       b'01100110' ; .GF..CB. = 4       
           retlw       b'01101101' ; .GF.DC.A = 5      
           retlw       b'01111101' ; .GFEDC.A = 6        
           retlw       b'00000111' ; .....CBA = 7                                     
           retlw       b'01111111' ; .GFEDCBA = 8                                     
           retlw       b'01101111' ; .GF.DCBA = 9                                


Прокоментируите пожалуиста, будет работать или нет?

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

Indic    call        TABLE        ; Загружаем на индикацию
        movwf       PORTB
        btfsc       Flag,0       ; Секунда прошла?
        goto        Indic        ; Если нет, то повторим индикацию

Зачем постоянно, в течении секунды выводить одно и то-же в порт ? Делайте это после того как пройдёт секунда. Т.е. после

decf        Secund,1     ; декрементируем Секунды, сохраняем в регистре

         xorlw       b'00111111'  ; Если прошла, то проверим вытолкнули ли 0?
        btfss       STATUS,2     ; Если в W был 00111111, то флаг поднимется
        goto        OGID         ; Если поднялся, то больше здесь делать нечего - на ОХРАНУ

Вы проверяете то, что пришло из таблицы. Я бы проверял саму переменную секунды (Secund) на 0, было бы правильнее. Т.е. проверил, если не ноль - декремент, если 0 - уходим в охрану.

Ссылка на комментарий
Поделиться на другие сайты

Зачем постоянно, в течении секунды выводить одно и то-же в порт ? Делайте это после того как пройдёт секунда. Т.е. после

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

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

Андрей, советую Вам переходить на Си. У Вас не плохо получается "вкуривать" эту тему, думаю что Си Вам только поможет.

Т.е. проверил, если не ноль - декремент, если 0 - уходим в охрану.
Извеняюсь, не так. Декркмент, вывод на индикатор, а потом проверка переменной на 0. Если 0 - охрана.

А в переменную Secund пишите не 9, а 10.

         movlw       .10
        movwf       Secund       ; количество секунд

Ссылка на комментарий
Поделиться на другие сайты

Еслиб, вы знали каким потом дается мне эта программа, я два дня ходил вокруг да около, кучу бумаги выкинул, а сегодня просто сел и начал писать, вроде получилось хоть и с ошибками, если б не вы незнаю чтоб я делал. Простите за оффтоп. Попробую начать изучать Си, только доделаю этот проект, кстати мне идут уже контроллеры, но совсем не 84а, придется этот код переписывать на другои контроллер и добавлять туда датчики температуры и GSM модуль и кодовый замок, но это уже совсем другая тема будет)))

Не цитируите полностью предыдущее сообщение!!!

Ссылка на комментарий
Поделиться на другие сайты

Поверьте, мы все потели когда начинали. Главное понимать что делать, а Вы как раз это прекрасно понимаете, у Вас отлично получается. На Си будет намного проще и быстрее писать программы. Так что не бойтесь, начинайте, мы Вам поможем.

Удачи...

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...