Реле Tianbo - ресурс 10 млн переключений

Непонятная ситуация с прерыванием PIC16F684

Новичок
 
Регистрация: 05.12.2012
Сообщений: 11
Репутация: 11
1 0
0 0
 
22.07.2024 14:50 #1
XC8 вер.2.46 MPLAB IDE PIC16F684 Уровень — Начинающий.

Задача - мигать четырьмя светодиодами с разной частотой. Реализовано на подсчёте прерываний от таймера TMR0.

Код:
============================
/*
* File: Base_PIC16F684.c
* Author: efimius
*
* Created on June 24, 2024, 2:07 PM
*/
// CONFIG
// PIN 2-LEDS button,PIN 11-MOTOR button,PIN 3=MUSIC button
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN =OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
#define OPTION_REG &= 0x7F
#define WPUA = 0x00
#define _XTAL_FREQ 4000000
#define MOTOR PORTCbits.RC5 //PIN #5 Launch DC motor
#define LIGHT_Y PORTCbits.RC3 //PIN #7 Controls yellow leds
#define LIGHT_B PORTCbits.RC2 //PIN #8 Controls blue leds
#define LIGHT_G PORTCbits.RC1 //PIN #9 Controls green leds
#define LIGHT_R PORTCbits.RC0 //PIN #10 Controls red leds
#define MUSIC PORTCbits.RC4 //PIN #6 Controls music chip
#define BUT3 PORTAbits.RA5 //PIN #2) TOGGLE BUTTON log "0" or log "1"
#define BUT2 PORTAbits.RA2 //PIN #11 TOGGLE BUTTON log "0" or log "1"
#define BUT1 PORTAbits.RA4 //PIN #3 TOGGLE BUTTON log "0" or log "1"


#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
int tickMOT=0;
int tickR=0;
int tickG=0;
int tickB=0;
int tickY=0;
//=======================================
void ROTATE(void)
{
tickMOT++;
if(tickMOT<=2)MOTOR=1;
else if(tickMOT>=3){MOTOR=0;tickMOT=0;}

}
//==============================================
void SONG(void)
{
if(BUT1==1) // IF toggle button3 is "ON" (log"1")
{
MUSIC=0; //Than set log "0" on PIN 10. launch music
}
else MUSIC=1;
}
//=====================================
void __interrupt() LEDS()
{
INTCONbits.T0IF=0; //Reset interrupt flag to 0
tickR++; //Increment counter interrupts f0r RED
tickG++; //Increment counter interrupts f0r GREEN
tickB++; //Increment counter interrupts f0r BLUE
tickY++; //Increment counter interrupts f0r YELLOW

{

if (tickR == 4000){LIGHT_R=!LIGHT_R; tickR=0;} //Toggle pin LIGHT_R
if (tickG == 3000){LIGHT_G=!LIGHT_G; tickG=0;} //Toggle pin LIGHT_G
if (tickB == 2000){LIGHT_B=!LIGHT_B; tickB=0;} //Toggle pin LIGHT_B
if (tickY == 1000){LIGHT_Y=!LIGHT_Y; tickY=0;} //Toggle pin LIGHT_Y
}
}
//================================================== =========void main(void
void main(void)
{
ANSEL=0x00000000; //Disconnect analog iputs
TRISA=0x11111111; //TRISA input
TRISC=0x00000000; //TRISC output
PORTA=0x11111111; //PORTA input
PORTC=0x00000000; //PORTC output
CMCON0=0x00000000;
ADCON0bits.ADON=0;
INTCONbits. GIE=1; //Enable all interrupts
INTCONbits.T0IF=0; //reset interrupt flag
INTCONbits.T0IE=1; //Enables TMR0 interruptOPTION_REGbits.
OPTION_REGbits.T0CS=0; //CLOCK- internal instruction cycle
OPTION_REGbits.PSA=1; //Pre scaler
OPTION_REGbits.PS0=1;
OPTION_REGbits.PS1=1;
OPTION_REGbits.PS2=1;
while(1);
}


На настоящий момент всё работает, но переключаются только синий и жёлтый светодиоды. На RC0 и RC1 логический "0".
Буду благодарен за любой совет.

Cbase.jpg
Последний раз редактировалось Admin; 22.07.2024 в 17:54.
Оценка
Знаток
 
Регистрация: 06.01.2010
Адрес: Львов
Сообщений: 238
Репутация: 125
111 165
3 2
 
22.07.2024 18:25 #2
Не в прерывании дело (хотя я туда не заглянул, полез сначала проверять инициализацию, ибо там обычно ошибки у большинства, в том числе и у меня). Компараторы не отключены. Судя по схеме, Вы их не используете. Должно быть так:
CMCON0 = 7. А у Вас пишется почему-то 0.
И ещё: ADCON0 = 0 (весь регистр, а не только один бит). Т.е. надо указать опору от VDD, а не от пина Vref, и выключить модуль АЦП.
Чтобы было меньше проблем, советую делать инициализацию не точечно, а полностью пройтись по всем регистрам, влияющим на настройку, и всё явно прописать в коде. И глобальный конфиг тоже проверять.
И ещё не понятно, зачем в схеме стоит ULN. Питать светодиоды можно и прямо от портов. Но если вместо светодиодов будут впоследствии мощные нагрузки - тогда да, оправдано.
Последний раз редактировалось Guaho; 22.07.2024 в 18:34.
Оценка
Новичок
 
Регистрация: 05.12.2012
Сообщений: 11
Репутация: 11
1 0
0 0
 
23.07.2024 00:35 #3
Цитата:
Сообщение от Guaho
Не в прерывании дело (хотя я туда не заглянул, полез сначала проверять инициализацию, ибо там обычно ошибки у большинства, в том числе и у меня). Компараторы не отключены. Судя по схеме, Вы их не используете. Должно быть так:
CMCON0 = 7. А у Вас пишется почему-то 0.
И ещё: ADCON0 = 0 (весь регистр, а не только один бит). Т.е. надо указать опору от VDD, а не от пина Vref, и выключить модуль АЦП.
Чтобы было меньше проблем, советую делать инициализацию не точечно, а полностью пройтись по всем регистрам, влияющим на настройку, и всё явно прописать в коде. И глобальный конфиг тоже проверять.
И ещё не понятно, зачем в схеме стоит ULN. Питать светодиоды можно и прямо от портов. Но если вместо светодиодов будут впоследствии мощные нагрузки - тогда да, оправдано.
Вы правы, я исправил
CMCON0=0x00000111;
ADCON0=0;
Но пока не работает, по-прежнему только синий и жёлтый, может с интераптом я чего-то напутал в логике. Буду думать.
Насчёт ULN, вы правы, должно быть по восемь запараллеленых светодиодов. PIC не потянет. Спасибо вам за вашу подсказку, буду думать дальше. Думаю с таймером что-то, потому что запрещал GIE, т.е. интеррапт и спокойно выводил на RC1 RC2 RC3 RC4 нули и единицы.
Оценка
Знаток
 
Регистрация: 06.01.2010
Адрес: Львов
Сообщений: 238
Репутация: 125
111 165
3 2
 
23.07.2024 07:20 #4
Если вне прерывания состояния проблемных светодиодов можно изменить - значит, переиферийные модули (АЦП, компараторы и прочее) не мешают выводу. Кроме того, два светодиода из 4-х меняют состояние - значит, вход в прерывание происходит. Код работы со светодиодами - одинаков, ничто не предвещает беды))
Посмотрите свой глобальный конфиг:
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN) - включен выход тактовой частоты на пине RA4, а там (да и вообще) это не нужно (линия кнопки).
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled) - Вот это ещё раз проверьте, точно ли отключен сторожевой таймер.
А в целом, навскидку, действительно непонятно, в чём проблема (я тоже начинающий). Тогда воспользуйтесь симулятором - это верное средство, не раз выручало. Поставьте точку останова в место инкремента счётчиков светодиодов и смотрите их состояние. Если не трудно, отпишитесь потом, в чём была проблема, самому интересно стало)
Да, и ещё (уже не по теме). Не увидел в коде фрагмента подавления дребезга клавиатуры (возможно, Вы просто его не привели). Штука обязательная, в реальном железе без этого будет проблема с управлением.
Последний раз редактировалось Guaho; 23.07.2024 в 07:27.
Оценка
Новичок
 
Регистрация: 05.12.2012
Сообщений: 11
Репутация: 11
1 0
0 0
 
24.07.2024 00:49 #5
Любопытная вещь. изменил в ISR порядок счётчиков по возрастанию:

{

if (tickR == 1000){LIGHT_R=!LIGHT_R; tickR=0;} //Toggle pin LIGHT_R
if (tickG == 2000){LIGHT_G=!LIGHT_G; tickG=0;} //Toggle pin LIGHT_G
if (tickB == 3000){LIGHT_B=!LIGHT_B; tickB=0;} //Toggle pin LIGHT_B
if (tickY == 4000){LIGHT_Y=!LIGHT_Y; tickY=0;} //Toggle pin LIGHT_Y
}

И всё заработало, как задумано, все светодиоды разноцветно мигают, казалось бы радуйся, но осадочек остался. Почему порядок возрастания счётчиков исправил ситуацию? Число в счётчиках не имеет значения, главное, чтобы они в ISR располагались по возрастанию. Даже при равенстве чисел в счётчиках, мигают только синий и жёлтый. Надеюсь, что гуру объяснят.
Оценка
Знаток
 
Регистрация: 06.01.2010
Адрес: Львов
Сообщений: 238
Репутация: 125
111 165
3 2
 
24.07.2024 07:39 #6
Не поленитесь, верните всё назад и прогоните код в симуляторе (в MPLAB-е). И посмотрите, что происходит с регистрами и счётчиками. Это самый надёжный вариант. Кроме того, в железе схема может повести себя иначе, чем в Протеусе, поэтому на последний нельзя 100%-но полагаться. И главное - что это? Повторюсь, симулятор MPLAB избавит Вас от гаданий. Но навскидку можно предположить, что это проблема RMW (http://www.knutselaar.eu/pdf/ReadModifyWrite.pdf) Похоже, изменение одних битов порта влияет на другие биты, потому перестановка команд и меняет дело. Я ловил такое как-то в железе (Протеусом не пользуюсь). Хорошим подходом для контроллеров среднего подсемейства является хранение образа порта в отдельном регистре. Все модификации битов Вы проводите только с этим регистром, а затем, в конце прерывания, выводите образ в физический порт. Ради интереса попробуйте этот вариант. Фактически здесь всего одна дополнительная команда, но этот подходит надёжно страхует от RMW. Я уже давно только так и работаю с портами.
А для манипуляций с битами можно использовать макросы, или, что ещё удобнее - использовать битовые структуры и объединения.
Оценка
Ответ
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Оценка этой теме
Оценка этой теме:
Похожие темы
Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход
Электронные компоненты. Скидки, кэшбэк и бесплатная доставка от ТМ Электроникс
Часовой пояс GMT +3, время: 12:57.
Обратная связь РадиоЛоцман Вверх