У меня возникла очень странная на мой взгляд проблема. Перешел к изучению програмирования МК на языке высокого уровня. Выбрал Си.
Написал пару очень простых задач из университетского курса. Но в обоих програмах возникла проблема с прерыванием. у меня на плате к прерыванию по внешнему срезу 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
Mar 18 2011, 12:04
Я бы в прерывании задержки не ставил...
мутное какое-то прерывание однако...мутное...
а ещё 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
Mar 18 2011, 15:45
У человека скорее всего "не работает" модель в протеусе.
Что будет делать программа когда перестанет выполняться условие while в main?
aaarrr
Mar 18 2011, 15:56
Цитата(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, 16:30
Цитата(Дар @ Mar 18 2011, 20:00)

У меня работает модель в протеусе. Аедь не может быть что бы на ассемблере програма выходила из прерывания а в си модель не работала.
Тогда в чем проблема?
Берете в пошаговой трассировке включаете ctrl-D(дизассемлер) - и разбор полетов.
Цитата(_Pasha @ Mar 18 2011, 18:30)

Тогда в чем проблема?
Берете в пошаговой трассировке включаете ctrl-D(дизассемлер) - и разбор полетов.
проблема в том что я вижу в дизасеблере как включаеться команда reti выходит в точку и тут же возвращаеться назад как будто кнопка нажата еще раз. то есть выходит и сразу заходит на зад на вектор прервания.
DpInRock
Mar 18 2011, 18:39
А какой именно 8051 вы используете.
---
Ибо вы куда-то дели настройку прерывания по фронту.
---
_Pasha
Mar 18 2011, 18:42
Цитата(Дар @ 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
Mar 19 2011, 06:30
Скакой частотой мигают диоды (оценочно - герцы, много герц).
Стоит ли большой конденсатор на кнопке.
Цитата(DpInRock @ Mar 19 2011, 08:30)

Скакой частотой мигают диоды (оценочно - герцы, много герц).
Стоит ли большой конденсатор на кнопке.
Ну я не знаю как определить частотоу мигания в герцах. но мне кажтеться не очень быстро(нет ну на вид так мелкают почти не разглядеть, но если учесть что если устроить мигание диодов в цикле без прерывания. то без задержки не будет видно как они зжаигаються и тухнут. Слишком быстро, будет видно что они как будто поагшены вся время). СКорость передчи 4800 бод. , а внутреяя частота процсора 11.0592 мГц.
стоит. но вот еще и картинка сехемы, что б в портеусе не открыватья макет(тем более что его может и не быть)
DpInRock
Mar 19 2011, 10:13
а реальная схема?
На проводках? Блокировочные конденсаторы, куда идет резет?
Выбросьт из программы лишнее - имею в виду принтэфы и прочая. Никаких сторонних библиотек.
я пробывал вырубать все оставляя только светодиоды и прерывание.
#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
Mar 19 2011, 13:38
Вы можете изъясняться маленько однозначнее?
Если вы имеете в виду снмок протеуса, то та схема работать не будет. Если реальная - точно такая же.
И что в схеме не так? и почему этого раньше никто не заметил. В КПИ уже 3 курс используют этот макет.
DpInRock
Mar 19 2011, 14:38
Макет от чего-то питается. От батареек?
Где блокировочные конденсаторы.
Почему некоторые входы (весьма значимые) висят в воздухе?
Не вижу конденсатора на кнопке. Если что-то слышали про дребез контактов, то нажатие на такую кнопку вызовет тучу прерываний.
В программе.
Туча прерываний очень связана с размером стека. Кто управляет у вас размером стека?
И так далее.
Кроме того, начинать программирование следует с программ, текст которых вы видите полностью.
Для изучения кнопки и светодиодов нет необходимости в использовании каких-либо внешних библиотек.
Должна быть одна строка include, которая содержит определение регистров. Больше ничего.
Спасибо за указания, попробую переделать макет. Хотя все еще не понимаю как по вашему функция atoi. и printf могут быть связаны с прерыванием(я их на ассеблере видел, ну то что отображаеться в cntrl+D).
Цитата(Дар @ Mar 18 2011, 22:04)

intel 8051AH
Дык, P3_3 - это вход INT1. А у вас на нём светодиод висит. Сами себя и загоняете в прерывание, когда светодиодом начинаете управлять, всё правильно...
бЛин точно, спасибо. это да, это дали маху.
только что попробывал вырубить, походу это не едиственый бок. так как не помогло.
Цитата(Дар @ Mar 19 2011, 20:28)

только что попробывал вырубить, походу это не едиственый бок. так как не помогло.
Кого? Кому? А? Что? Где я?
диод который на порте 3_3
Цитата(Дар @ Mar 19 2011, 23:01)

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

Собстно, поэтому и интересуюсь, что же там "не помогло"
А я знаю, как ето называеццо.
"Пляска Святого Витта."
Во!
Цитата(SysRq @ Mar 19 2011, 22:27)

Ну Proteus вполне себе переключает два оставшихся на каждое четвертое нажатие кнопки, согласно логике выложенной вами выше (#15) программы (а на P3_5 еще пищалка висит у вас, дада). Собстно, поэтому и интересуюсь, что же там "не помогло", и чего ж надобно-то?
не помогло, изтятие из програмы 3 диода, оставил только два. тоже самое. заскакивает в прервание сраху после выхода.
Цитата(Дар @ Mar 20 2011, 15:16)

не помогло, изтятие из програмы 3 диода, оставил только два.
Дайте KEIL'овский проект целиком, посмотрим..
--
Цитата(_Pasha @ Mar 20 2011, 14:49)

"Пляска Святого Витта."
Ну и аватарка у него в Википедии
DpInRock
Mar 20 2011, 17:28
Обалдеть. Т.е. "программа на ассемблере работала" - чистое вранье?
Цитата(Дар @ Mar 20 2011, 18:42)

Вот Проэкт.
0) Где файл "DEBUG.A51"?
1) Опции проекта таковы, что ни *.hex, ни что иное, пригодное для Proteus'а\прогрмматора, не создаётся. Отладчик KEIL'а настроен на что-то внешнее (не симулятор). Собственно, чем же вы проверяете работоспособность?
2) В опциях linker'а жёстко задан начальный адрес сегмента кода (и не только). Значение не является верным для 8051AH. В Proteus'е работать будет, в реальном МК - нет.
Ежели собрать проект со стандартным startup'ом, то в Proteus'е, в вашей же схеме, оно исправно работает...
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.