![]() |
|
|
Вопросы начинающих Прежде чем задать вопрос, стоит воспользоваться поиском |
![]() |
|
Опции темы | Опции просмотра |
![]() |
#1 |
Junior Member
Регистрация: 28.11.2014
Сообщений: 2
Вес репутации: 100/0 ![]() ![]() |
![]()
Здравствуйте!
Как начинающий, занимаюсь морганием светодиодов, написал вот такую программку (Product Version: MPLAB X IDE v2.26, System: Linux version 3.0.3-std-def-alt0.M60P.1 running on i386; UTF-8; ru_RU (mplab) Код:
#include <xc.h> #include <pic12f675.h> // CONFIG #pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled) #pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled) #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) #define LED_5 GPIO5 #define LED_4 GPIO4 #define LED_3 GPIO2 #define LED_2 GPIO1 #define LED_1 GPIO0 #define led_on 1 #define led_off 0 volatile unsigned int RTC = 0; //глобальная переменная void interrupt TMR0_int(void) //прерывание от таймера 0 { if (T0IF) //если сработало прерывание от таймера { T0IF = 0; //сбросить бит прерывания RTC++; //RTC увеличить на 1 } } void DELAY(void) //функция "задержка" { unsigned int dlay = 0; //инициализация переменной dlay = 256 + RTC; // к RTC прибавляем 256 мс while (dlay != RTC); //ждём эти самые 256 мс } void INIT(void) //инициализация { T0CS = 0; //Выбор тактового сигнала для TMR0, внутренний тактовый сигнал PSA = 0; //предделитель включен перед TMR0 PS0 = 1; //предделитель, коэффициент деления 1:4 PS1 = 0; //предделитель, коэффициент деления 1:4 PS2 = 0; //предделитель, коэффициент деления 1:4 T0IE = 1; //Разрешение прерывания по переполнению TMR0 GIE = 1; //Глобальное разрешение прерываний TMR0 = 0; //сброс таймера TRISIO5 = 0; // канал работает как выход TRISIO4 = 0; // канал работает как выход TRISIO3 = 1; // канал работает как вход(всегда) TRISIO2 = 0; // канал работает как выход TRISIO1 = 0; // канал работает как выход TRISIO0 = 0; // канал работает как выход GPIO5 = 0; //светодиод потушен GPIO4 = 0; //светодиод потушен GPIO2 = 0; //светодиод потушен GPIO1 = 0; //светодиод потушен GPIO0 = 0; //светодиод потушен } int main(void) { INIT(); while(1) { LED_5 = led_on; //включаем 5-й светодиод DELAY(); //задержка LED_4 = led_on; //включаем 4-й светодиод DELAY(); LED_3 = led_on; //и т.д. DELAY(); LED_2 = led_on; DELAY(); LED_1 = led_on; DELAY(); LED_5 = led_off; //выключаем 5-й светодиод DELAY(); //задержка LED_4 = led_off; //выключаем 4-й светодиод DELAY(); LED_3 = led_off; //и т.д. DELAY(); LED_2 = led_off; DELAY(); LED_1 = led_off; DELAY(); } } Но получается так: загорается 5-й светодиод, затем 4-й, потом 5-й продолжает гореть, 4-й гаснет и включается 3-й и т.д; 5-й горит постоянно, а вот с 4-го по 1-й - это "бегущий огонь". Потом выключается 5-й светодиод и программа просто отрабатывает несколько задержек при выключенных остальных светодиодах. Пробовал сделать так: Код:
GPIO5=1;//включаем светодиод DELAY(); GPIO4=1;//включаем светодиод ... Код:
asm (" bsf GPIO,0"); //включаем светодиод DELAYY(); asm (" bsf GPIO,1"); //включаем светодиод ... Код:
list p=12f675 ; list directive to define processor #include </1/1.1> ; это вместо </opt/microchip/mplabx/mpasmx/p12f675.inc> __CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_OFF &_INTRC_OSC_NOCLKOUT ;_CP_OFF - Program Memory code protection is disabled ;_CPD_OFF - Data memory code protection is disabled ;_BODEN_OFF - BOD disabled ;_MCLRE_OFF - GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD ;_WDT_OFF - WDT disabled ;_PWRTE_OFF - PWRT disabled ;_INTRC_OSC_NOCLKOUT - INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN ; ==ИНИЦИАЛИЗАЦИЯ bcf STATUS,RP0 ; Установить банк 0 clrf GPIO ; Нулим весь порт movlw 0x07 ; все каналы - цифровые входы-выходы movwf CMCON bsf STATUS,RP0 ; Установить банк 1 movlw b'00000000' ; GP 0,1,2,4,5 на выход movwf TRISIO ; Но все равно GP3 всегда будет на вход movlw b'00000000' ; Выключить подтяжку(резистор) movwf WPU ; Подтягивающие резисторы выключены movlw b'00000000' ; movwf T1CON ; Отключить TMR1 movlw b'00000111' ; таймер0 работает от внутреннего генератора, movwf OPTION_REG ; предделитель 256 movlw b'00000000' ; movwf VRCON ; Отключить источник опорного напряжения clrf INTCON ; запретить все прерывания ; ЗАГРУЗИМ КАЛИБРОВОЧНУЮ КОНСТАНТУ call 3FFh ; калибровочная константа из документации movwf OSCCAL ; ЗАГРУЗИТЬ КАЛИБРОВОЧНУЮ КОНСТАНТУ ;================= bcf STATUS,RP0 ; Установить банк 0 movlw 0x00 ; обнуляем таймер movwf TMR0 main bsf GPIO,0 call delay bsf GPIO,1 call delay bsf GPIO,2 call delay bsf GPIO,4 call delay bsf GPIO,5 call delay bcf GPIO,0 call delay bcf GPIO,1 call delay bcf GPIO,2 call delay bcf GPIO,4 call delay bcf GPIO,5 call delay goto main ;==конец основной проги delay bcf STATUS,RP0 ; Установить банк 0 movf 0x00,0 movwf TMR0 ; обнуляем таймер vr btfss INTCON,T0IF ; проверяем переполнение таймера0 goto vr bcf INTCON,T0IF ; устанавливаем в 0 бит переполнения таймера0 return ;=========================== end Код:
GPIO = 0b0000001; //включаем 1 светодиод DELAY(); //задержка GPIO = 0b0000011; //включаем 2 светодиода и т.д. Кто знает - в чём здесь дело? |
![]() |
![]() |
![]() |
#2 |
Senior Member
Регистрация: 28.06.2013
Возраст: 46
Сообщений: 675
Вес репутации: 1432/38 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]()
Не могу не отметить, что вопрос хорошо поставлен, автор молодец! Проблема описана чётко, не приходится включать дар предвидения
![]() По сути вопроса: сделайте переменную, в ней проводите битовые манипуляции, а потом этот байт выводите в порт (кстати, такой вывод можно делать и в прерывании, что повысит удобство работы: в этом случае Вы будете в основном цикле выполнять битовые операции с упомянутым регистром, а вывод будет происходить "сам собой"). Лично я никогда не дёргаю биты портов напрямую во избежание проблем (пресловутое "чтение-модификация-запись"). |
![]() |
![]() |
![]() |
#3 |
Senior Member
Регистрация: 05.06.2007
Возраст: 46
Сообщений: 3,674
Вес репутации: 6112/137 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]()
Кроме компаратора есть еще ADC .
![]() Собственно в даташите есть инит GPIO ... ![]() Последний раз редактировалось dosikus; 30.11.2014 в 13:21. |
![]() |
![]() |
![]() |
#4 |
Senior Member
|
![]()
Если Вы думаете, что команды BCF и BSF дергают только один бит, то Вы заблуждаетесь, они все равно весь порт дергают, потому как работает чтение - модификация - запись (RMW).
__________________
License MikroC, MikroC PRO and EasyPIC5 by mikroElektronika (the dead mikroICD replaced PICKit2 & PICKit3) |
![]() |
![]() |
![]() |
#5 |
Senior Member
Регистрация: 06.09.2008
Возраст: 56
Сообщений: 239
Вес репутации: 227/40 ![]() ![]() ![]() |
![]()
Если порт правильно нагружен, то никаких проблем с RMW не будет.
Как подключены светодиоды? |
![]() |
![]() |
![]() |
#6 |
Super Moderator
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,698
Вес репутации: 5252/159 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
![]() |
![]() |
#7 |
Senior Member
Регистрация: 06.09.2008
Возраст: 56
Сообщений: 239
Вес репутации: 227/40 ![]() ![]() ![]() |
![]()
Но ведь при этом порт вообще будет ВХОДОМ! Тогда вообще нет смысла подключать к нему светодиод. Или нет?
|
![]() |
![]() |
![]() |
#8 |
Super Moderator
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,698
Вес репутации: 5252/159 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]()
порт настроен на выход. при попытке установки единичного бита считывается весь порт (его входы), изменяется (устанавливается) нужный бит, и всё записывается назад. Если выходы были перегружены (ваш вопрос) или на них при чтении был ноль из-за неверной конфигурации, то будет этот самый rmw
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Регистрация: 06.09.2008
Возраст: 56
Сообщений: 239
Вес репутации: 227/40 ![]() ![]() ![]() |
![]()
Вот для этого и была фраза: "Если порт ПРАВИЛЬНО нагружен".
|
![]() |
![]() |
![]() |
#10 |
Junior Member
Регистрация: 28.11.2014
Сообщений: 2
Вес репутации: 100/0 ![]() ![]() |
![]()
Спасибо за подсказки, я посчитал что при включении питания достаточно того, что бит ADON устанавливается в 0.
Проблема решена добавлением в секцию INIT вот такого Код:
... TMR0 = 0; //сброс таймера ANS0 = 0; // цифровой канал порта ввода/вывода или специальные функции ANS1 = 0; // а не АЦП ANS2 = 0; ANS3 = 0; CM0 = 1; //компаратор выключен CM1 = 1; //см. стр. 37, документ DS41190A CM2 = 1; // TRISIO5 = 0; // канал работает как выход ... Последний раз редактировалось Greg; 30.11.2014 в 14:54. |
![]() |
![]() |
![]() |
#11 |
Super Moderator
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,698
Вес репутации: 5252/159 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]()
для меня ключевое слово было - "нагружен". Если порт (нога) настроен как вход adc, то даже если к нему вообще электрически ничего не подключено, читаться там будет 0. и соответственно писаться назад.
что забавно, в больших камнях (те же армы) под (проблемой) rmw обычно понимается совершенно другое - т.н. атомарность операции, т.е. чтобы в процессе чтения-записи не произошло прерывание и не изменило переменную. |
![]() |
![]() |
![]() |
#12 | |
Senior Member
Регистрация: 28.06.2013
Возраст: 46
Сообщений: 675
Вес репутации: 1432/38 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() Цитата:
![]() |
|
![]() |
![]() |
![]() |
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1) | |
Опции темы | |
Опции просмотра | |
|
|
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Чем/как отлаживать код написаный на Си в WinAVR | Yokel | Микроконтроллеры других производителей | 49 | 30.09.2014 09:48 |
H-мост работает не как положено | dccharacter | Вопросы начинающих | 1 | 21.11.2010 19:12 |
Макимальная частота прерываний от TMR0 | ANH | Продукция MICROCHIP | 114 | 05.04.2008 00:50 |