Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не выходит из прерывание по Инт1. Пишу на СИ для 8051
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Дар
У меня возникла очень странная на мой взгляд проблема. Перешел к изучению програмирования МК на языке высокого уровня. Выбрал Си.
Написал пару очень простых задач из университетского курса. Но в обоих програмах возникла проблема с прерыванием. у меня на плате к прерыванию по внешнему срезу 1- подключена кнопка. При нажатии на кнопку, в прерывание попадает как и положенно. А вот потом я так и не понял толи у меня из прерывания вообше не выходит, то ли выходит но сразу запрыгивает назад. итог один. прерывание после одной активации работает как зацикленную функцию. Не могу понять в чем дело?
те же проги на асемблере у меня выходили нормально.
Пример. программы. Прграмма не сложная должна инвертировать светодиоды, после определенного нажатия нак кнопку. ( а делает: после вызова прерывания 1 раз. прерывание циклиться и светдиоды просто мигают постоянно)
#include <reg51.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
//#include <avr/io.h>
//#include <avr/interrupt.h>

sbit P3_5 = P3^5; \\ светодиод1
sbit P3_4 = P3^4; \\ светодиод 2
sbit P3_3 = P3^3; \\ светодиод 3

static unsigned int delay = 0;
char xdata str[20];
unsigned int N;
int i ;
int b = 0;
int c = 0;
int a = 1;
/* начало коментария
// enter MK to PowerDown while int1 = 0
void EnterPowerDown(void)
{
MCUCR = (1 << SE) | (1 << SM1); // int1 level sensitive + power-down
GICR = (1 << INT1);
asm("sleep");
}


//enter MK in idle mode, while INT1 in zero.
void WaitOnInt1ToGetHigh(void)
{
if (PIND & (1 << PD3)) // INT1 high?
{ // the level already high, no need to go idle
return;
}

MCUCR = (1 << SE) | (1 << ISC11) | (1 << ISC10); // int1 on rising edge + idle
GICR = (1 << INT1);
asm("sleep");
}*/ закоментированная часть проги, подозреваю что не для той версии кейла, или вообще не к этому процесору.

void initialize_system (void){
SCON = 0x52;
TMOD |= 0x20;
TH1 = 0xFa;
TR1 = 1;
TI = 1;
}

unsigned int num_element() {
printf("\nEnter the number of push on button Int1 for invert led\n",str);
gets (str, sizeof(str));
N = atoi(str); // ASCII to integer
return N;
}

void intrrupt_butInt1(void) interrupt 2
{
if (N >= i){
i = 0;
if (a == 1, b == 0, c == 0){
a = 0;
b = 1;
c = 1;
}
else{
a = 1;
b = 0;
c = 0;
}
P3_3 = a;
P3_4 = b;
P3_5 = c;
for (delay = 0; delay < 0x1FF; delay++);
}
else {i++;} // WHY? WHEN cursor CAME TO THIS POINT, JUMP TO BEGIN INTERRUPT. BUT DON'T T0 MAIN
}

void main( void ){
P3 ^= 0x00;
initialize_system();
for (delay = 0; delay < 0x1FFF; delay++);
P3_3 = a;
P3_4 = b;
P3_5 = c;
N = num_element();
while(TH0 < 6){
TCON |=0x04;
IE |=0x84;
}

}

макет платы на протеусе прилагаеться.
sigmaN
Я бы в прерывании задержки не ставил...
мутное какое-то прерывание однако...мутное...

а ещё volatile на все глобальные переменные, которые используются в прерывании - прописная истина же.
Дар
У меня возникла очень странная на мой взгляд проблема. Перешел к изучению програмирования МК на языке высокого уровня. Выбрал Си.
Написал пару очень простых задач из университетского курса. Но в обоих програмах возникла проблема с прерыванием. у меня на плате к прерыванию по внешнему срезу 1- подключена кнопка. При нажатии на кнопку, в прерывание попадает как и положенно. А вот потом я так и не понял толи у меня из прерывания вообше не выходит, то ли выходит но сразу запрыгивает назад. итог один. прерывание после одной активации работает как зацикленную функцию. Не могу понять в чем дело?
те же проги на асемблере у меня выходили нормально.
Пример. программы. Прграмма не сложная должна инвертировать светодиоды, после определенного нажатия нак кнопку. ( а делает: после вызова прерывания 1 раз. прерывание циклиться и светдиоды просто мигают постоянно)
#include <reg51.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "C:\Keil\C51\inc\Pprintf.h"
#include "C:\Keil\C51\inc\kscanf.h"

sbit P3_5 = P3^5;
sbit P3_4 = P3^4;
sbit P3_3 = P3^3;

static unsigned int delay = 0;
char xdata str[200];
unsigned int N;
unsigned int A;
unsigned int i = 0;
int b = 0;
int c = 0;
int a = 1;

void initialize_system (void){
SCON = 0x52;
TMOD |= 0x20;
TH1 = 0xFa;
TR1 = 1;
TI = 1;

P3_3 = a;
P3_4 = b;
P3_5 = c;

EA = 1;
EX1 = 1;
IT1 = 1;
}

unsigned int num_element() {
printf("\nEnter the number of push on button Int1 for invert led\n",str);
gets (str, sizeof(str));
N = atoi(str); // ASCII to integer
return N;
}

void intrrupt_butInt1(void) interrupt 2
{
if (i == N - 1){
i = 0;
if (a == 1, b == 0, c == 0){
a = 0;
b = 1;
c = 1;
}
else{
a = 1;
b = 0;
c = 0;
}
P3_3 = a;
P3_4 = b;
P3_5 = c;
}
i++; // WHY WHEN cursor CAME TO THIS POINT, JUMP TO BEGIN INTERRUPT. BUT DON'T T0 MAIN
// IE1 = 0; если активировать то выйдет, но назад по нажатиюю кнопки не попадет.
}

void main( void ){
P3 ^= 0x00;
initialize_system();
for (delay = 0; delay < 0x1FFF; delay++);
N = num_element();
kscanf(str);
A = atoi(str);
while(TH0 < A){
pprintf(str);
}

}
макет платы на протеусе прилагаеться.

DpInRock
У человека скорее всего "не работает" модель в протеусе.

Что будет делать программа когда перестанет выполняться условие while в main?

aaarrr
Цитата(sigmaN @ Mar 18 2011, 15:04) *
а ещё volatile на все глобальные переменные, которые используются в прерывании - прописная истина же.

Это не прописная истина, а известное заблуждение. Зачем на воду-то дуть?
Дар
Цитата(DpInRock @ Mar 18 2011, 17:45) *
У человека скорее всего "не работает" модель в протеусе.

Что будет делать программа когда перестанет выполняться условие while в main?

У меня работает модель в протеусе. Аедь не может быть что бы на ассемблере програма выходила из прерывания а в си модель не работала.
я пробывал делать while бесконечный. тоже самое.

Цитата(sigmaN @ Mar 18 2011, 14:04) *
Я бы в прерывании задержки не ставил...
мутное какое-то прерывание однако...мутное...

а ещё volatile на все глобальные переменные, которые используются в прерывании - прописная истина же.

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

переписывал с таким концом void main( void ){
P3 ^= 0x00;
initialize_system();
for (delay = 0; delay < 0x1FFF; delay++);
N = num_element();
// kscanf(sss);
// L = atoi(sss);
while(TH0 < 10){
L++;
// pprintf(L);
}

}
цикл Вайл теперь бесконечный, не помогло.
_Pasha
Цитата(Дар @ Mar 18 2011, 20:00) *
У меня работает модель в протеусе. Аедь не может быть что бы на ассемблере програма выходила из прерывания а в си модель не работала.

Тогда в чем проблема?
Берете в пошаговой трассировке включаете ctrl-D(дизассемлер) - и разбор полетов.
Дар
Цитата(_Pasha @ Mar 18 2011, 18:30) *
Тогда в чем проблема?
Берете в пошаговой трассировке включаете ctrl-D(дизассемлер) - и разбор полетов.

проблема в том что я вижу в дизасеблере как включаеться команда reti выходит в точку и тут же возвращаеться назад как будто кнопка нажата еще раз. то есть выходит и сразу заходит на зад на вектор прервания.
DpInRock
А какой именно 8051 вы используете.
---
Ибо вы куда-то дели настройку прерывания по фронту.
---
_Pasha
Цитата(Дар @ Mar 18 2011, 19:51) *
проблема в том что я вижу в дизасеблере как включаеться команда reti выходит в точку и тут же возвращаеться назад как будто кнопка нажата еще раз. то есть выходит и сразу заходит на зад на вектор прервания.

И шо показывает SP?
И когда заходит - хоть одну команду выполняет или нет?
Дар
Цитата(DpInRock @ Mar 18 2011, 20:39) *
А какой именно 8051 вы используете.
---
Ибо вы куда-то дели настройку прерывания по фронту.
---

intel 8051AH

EA =1; разрешение всех прерываний
EX1 IE.2 Бит разрешения внешнего прерывания 1. Установка/сброс программой для разрешения/запрета прерываний.
IT1 ОН ЖЕ TCON.2 Бит управления типом прерывания 1. Устанавливается/ сбрасывается программно для спецификации запроса ЗПР1/ (срез/низкий уровень).

IE1 TCON.3 Флаг фронта прерывания 1. Устанавливается аппаратно, когда детектируется срез внешнего сигнала ЗПР1/ (INT1/) Сбрасывается при обслуживании прерывания . ЕСЛИ УСТАНОВИТЬ ЭТОТ БИТ В РУЧНУЮ ТО ПРОСТО БУДЕТ ПОПАДПТЬ В ПРЕРЫВАНИЕ БЕЗНАЖАТИЯ НА КНОПКУ. тАК ЧТО Я НЕ ПОНЯЛ О КАКОЙ НАСТРОЙКЕ МЕНЯ СПРАШИВАЛИ, ЕСЛИ МОЖНО ОБЬЯСНИ.

TCON |=0x04;
IE |=0x84;
ТОЧНО ТАКИЕ ЖЕ НАСТРОЙКИ, ТОЛЬКО НЕ ПО БИТОВО , А НАПРЯМУЮ В РЕГИСТРЫ

//
Цитата(_Pasha @ Mar 18 2011, 20:42) *
И шо показывает SP?
И когда заходит - хоть одну команду выполняет или нет?


да когда повторно попадает\заходит в прерывание выполняет все команды в нем.
SP ? А что сп востанавливаеться. после выхода, и ояпть меняеться после вход. только очень быстро не пошагово не видно. если в числах(хотя не знаю что это может показать то sp=0x2f в main и 31 при начаде прерывания, потом 35 и опять 2а после reti и след шагом снова 31.) Я очень подробно описываю и часто повторяюсь по старой привычке инфы мало не бывает.


DpInRock
Скакой частотой мигают диоды (оценочно - герцы, много герц).
Стоит ли большой конденсатор на кнопке.
Дар
Цитата(DpInRock @ Mar 19 2011, 08:30) *
Скакой частотой мигают диоды (оценочно - герцы, много герц).
Стоит ли большой конденсатор на кнопке.

Ну я не знаю как определить частотоу мигания в герцах. но мне кажтеться не очень быстро(нет ну на вид так мелкают почти не разглядеть, но если учесть что если устроить мигание диодов в цикле без прерывания. то без задержки не будет видно как они зжаигаються и тухнут. Слишком быстро, будет видно что они как будто поагшены вся время). СКорость передчи 4800 бод. , а внутреяя частота процсора 11.0592 мГц.
стоит. но вот еще и картинка сехемы, что б в портеусе не открыватья макет(тем более что его может и не быть)
DpInRock
а реальная схема?
На проводках? Блокировочные конденсаторы, куда идет резет?
Выбросьт из программы лишнее - имею в виду принтэфы и прочая. Никаких сторонних библиотек.
Дар
я пробывал вырубать все оставляя только светодиоды и прерывание.
#include <reg51.h>
//#include <stdlib.h>
//#include <stdio.h>


sbit P3_5 = P3^5;
sbit P3_4 = P3^4;
sbit P3_3 = P3^3;

static unsigned int delay = 0;
char xdata str[200];
//volatile int N;
unsigned int L = 1;
unsigned int i = 0;
unsigned int a = 1;
unsigned int b = 0;
unsigned int c = 0;

void initialize_system (void){
// SCON = 0x52;
// TMOD |= 0x20;
// TH1 = 0xFa;
// TR1 = 1;
// TI = 1;

P3_3 = a;
P3_4 = b;
P3_5 = c;

TCON |=0x04; // 3
IE |=0x84;

}

/* unsigned int num_element() {
printf("\nEnter the number of push on button Int1 for invert led\n",str);
gets (str, sizeof(str));
N = atoi(str); // ASCII to integer
return N;
}
*/
void intrrupt_butInt1(void) interrupt 2
{
while (i == 5 - 1){
i = 0;
if (a == 1, b == 0, c == 0){
a = 0;
b = 1;
c = 1;
}
else {
a = 1;
b = 0;
c = 0;
}
P3_3 = a;
P3_4 = b;
P3_5 = c;
}
i++;
// IE1 = 0;
}

void main( void ){
P3 ^= 0x00;
initialize_system();
for (delay = 0; delay < 0x1FFF; delay++);
// N = num_element();
while(TH0 < 10){
L++;
}
}

тот же эфект. Не понятно вообще ничего. почему при записи на языке Асм вся норально, а на Си. такая хрен. ведь не олжно быть разницы. посути в дизасемблировании то эе самоенаписано.
Дар
реальная схема в аудитории. но макет с нее делался.
DpInRock
Вы можете изъясняться маленько однозначнее?

Если вы имеете в виду снмок протеуса, то та схема работать не будет. Если реальная - точно такая же.
Дар
И что в схеме не так? и почему этого раньше никто не заметил. В КПИ уже 3 курс используют этот макет.
DpInRock
Макет от чего-то питается. От батареек?
Где блокировочные конденсаторы.
Почему некоторые входы (весьма значимые) висят в воздухе?
Не вижу конденсатора на кнопке. Если что-то слышали про дребез контактов, то нажатие на такую кнопку вызовет тучу прерываний.

В программе.
Туча прерываний очень связана с размером стека. Кто управляет у вас размером стека?
И так далее.

Кроме того, начинать программирование следует с программ, текст которых вы видите полностью.
Для изучения кнопки и светодиодов нет необходимости в использовании каких-либо внешних библиотек.

Должна быть одна строка include, которая содержит определение регистров. Больше ничего.



Дар
Спасибо за указания, попробую переделать макет. Хотя все еще не понимаю как по вашему функция atoi. и printf могут быть связаны с прерыванием(я их на ассеблере видел, ну то что отображаеться в cntrl+D).
SysRq
Цитата(Дар @ Mar 18 2011, 22:04) *
intel 8051AH
Дык, P3_3 - это вход INT1. А у вас на нём светодиод висит. Сами себя и загоняете в прерывание, когда светодиодом начинаете управлять, всё правильно...
Дар
бЛин точно, спасибо. это да, это дали маху.

только что попробывал вырубить, походу это не едиственый бок. так как не помогло.
SysRq
Цитата(Дар @ Mar 19 2011, 20:28) *
только что попробывал вырубить, походу это не едиственый бок. так как не помогло.
Кого? Кому? А? Что? Где я? sm.gif
Дар
диод который на порте 3_3
SysRq
Цитата(Дар @ Mar 19 2011, 23:01) *
диод который на порте 3_3
Ну Proteus вполне себе переключает два оставшихся на каждое четвертое нажатие кнопки, согласно логике выложенной вами выше (#15) программы (а на P3_5 еще пищалка висит у вас, дада). Собстно, поэтому и интересуюсь, что же там "не помогло", и чего ж надобно-то?
_Pasha
Цитата(SysRq @ Mar 19 2011, 23:27) *
Собстно, поэтому и интересуюсь, что же там "не помогло"

А я знаю, как ето называеццо.
"Пляска Святого Витта."
Во!
Дар
Цитата(SysRq @ Mar 19 2011, 22:27) *
Ну Proteus вполне себе переключает два оставшихся на каждое четвертое нажатие кнопки, согласно логике выложенной вами выше (#15) программы (а на P3_5 еще пищалка висит у вас, дада). Собстно, поэтому и интересуюсь, что же там "не помогло", и чего ж надобно-то?


не помогло, изтятие из програмы 3 диода, оставил только два. тоже самое. заскакивает в прервание сраху после выхода.
SysRq
Цитата(Дар @ Mar 20 2011, 15:16) *
не помогло, изтятие из програмы 3 диода, оставил только два.
Дайте KEIL'овский проект целиком, посмотрим..

--

Цитата(_Pasha @ Mar 20 2011, 14:49) *
"Пляска Святого Витта."
Ну и аватарка у него в Википедии biggrin.gif
Дар
Вот Проэкт.
DpInRock
Обалдеть. Т.е. "программа на ассемблере работала" - чистое вранье?
SysRq
Цитата(Дар @ Mar 20 2011, 18:42) *
Вот Проэкт.
0) Где файл "DEBUG.A51"?
1) Опции проекта таковы, что ни *.hex, ни что иное, пригодное для Proteus'а\прогрмматора, не создаётся. Отладчик KEIL'а настроен на что-то внешнее (не симулятор). Собственно, чем же вы проверяете работоспособность?
2) В опциях linker'а жёстко задан начальный адрес сегмента кода (и не только). Значение не является верным для 8051AH. В Proteus'е работать будет, в реальном МК - нет.

Ежели собрать проект со стандартным startup'ом, то в Proteus'е, в вашей же схеме, оно исправно работает...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.