Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Зависает МК при работе в подпрограмме, вызываемой по прерыванию.


Зависает МК при работе в подпрограмме, вызываемой по прерыванию.

Сообщений 1 страница 12 из 12

1

Джентльмены, давно читаю этот форум, но пока что удавалось находить ответы на возникающие вопросы по поиску. А тут что-то не выходит.
Подскажите по такому вопросу.
Схема простая. Тини 13. Две кнопки. Два выхода. На выходах ШИМ. Каждому каналу (правый и левый канал) ШИМ соответствует включающий его переключатель. ШИМ должен плавно зажечь светодиод от мин до макс при срабатывании своего тумблера. Когда тумблер отожмется, то ШИМ должен плавно погасить от макс до мин светодиод своего канал. Так вроде бы все работает. Но иногда зависает выполнение программы. Проявляется это тем, что, допустим, зажегся COMPARE0A и после отжатия кнопки не потухает. Или потухает, но не плавно а резко.
Тестировалось все это на реальной макетной плате (т.е, никаких протеусов и прочего софта).

http://b.a.d-cd.net/db37904s-960.gif

Код:
$regfile = "attiny13.dat"
$crystal = 9600000
$hwstack = 10
$swstack = 20
$framesize = 20

Config Portb.0 = Output : Portb.0 = 0                       'Выход ШИМ, право
Config Portb.1 = Output : Portb.1 = 0                       'Выход ШИМ, лево
Config Portb.2 = Output : Portb.2 = 0
Config Portb.3 = Input : Portb.3 = 1                        'Вход концевик, лево
Config Portb.4 = Input : Portb.4 = 1                        'Вход концевик, право
Compare0a = 255
Compare0b = 255

Rkon Alias Pinb.4
Lkon Alias Pinb.3
Rlamp Alias Compare0a
Llamp Alias Compare0b

Config Timer0 = Pwm , Compare A = Clear , Compare B = Clear , Prescale = 1

On Int0 Koncevik
Enable Int0
Config Int0 = Low Level
Enable Interrupts
Pcmsk.0 = 0
Pcmsk.1 = 0
Pcmsk.2 = 0
Pcmsk.3 = 1
Pcmsk.4 = 1

Dim A As Byte
Dim L As Byte
Dim L1 As Byte
Dim R As Byte
Dim R1 As Byte
Dim Delay_up As Byte
Dim Delay_down As Byte
Dim Step_l As Byte
Dim Step_r As Byte
Dim N As Byte
Dim M As Byte

Declare Sub Main
Declare Sub L_pwm_up
Declare Sub R_pwm_up
Declare Sub L_pwm_down
Declare Sub R_pwm_down

A = 0
Delay_up = 1
Delay_down = 2

'------ основной цикл - здоровый и молодецкий сон
Do
 Powerdown
Loop
End                                                         'end program

'подрограмма обработки нажания концевиков
'левого и правого канала
Koncevik:
' If Rkon = 0 Then Call Main
' If Lkon = 0 Then Call Main
 If Rkon = 0 Or Lkon = 0 Then Call Main
 Gifr = 64

Return

Sub Main
 R1 = 0
 L1 = 0
  Do
    'если соответствующий концевик только нажался
    'то разжигаем огон на соответсвуещем ШИМ
    'соответствующей подпрограммой
    If Rkon = 0 And Rlamp = 255 Then Call R_pwm_up
    If Lkon = 0 And Llamp = 255 Then Call L_pwm_up

    'если соответствующий концевик уже нажат (ШИМ = maximum)
    'при отпускании концевика гасим ШИМ соответсвующего
    'канал соответствующеей подпрограммой
    If Rkon = 1 And Rlamp = 0 Then Call R_pwm_down
    If Lkon = 1 And Llamp = 0 Then Call L_pwm_down

    'если оба концевика отжата, то выходим из петли
    'и возвращаемся в сон
    If Rkon = 1 And Lkon = 1 Then Exit Do
  Loop
 End Sub Main


'--подпрограмма розжига правого канала
Sub R_pwm_up
   R1 = 1
    For R = 255 To 0 Step -1
      Rlamp = R
      Waitms Delay_up
    Next R
End Sub R_pwm_up

'--подпрограмма розжига левого канала
Sub L_pwm_up
   L1 = 1
    For L = 255 To 0 Step -1
      Llamp = L
      Waitms Delay_up
    Next L
End Sub L_pwm_up

'--подпрограмма тушения правого канала
Sub R_pwm_down
   R1 = 1
   For R = 0 To 255 Step 1
     Rlamp = R
     Waitms Delay_down
   Next R
End Sub R_pwm_down

'--подпрограмма тушения левого канала
Sub L_pwm_down
   L1 = 0
   For L = 0 To 255 Step 1
     Llamp = L
     Waitms Delay_down
   Next L
End Sub L_pwm_down

0

2

Mrshilov написал(а):

Удивительно, что вообще как-то работает - прерывание назначено по Int0, а на этой ноге выход ШИМ.

Отредактировано Mrshilov (Сегодня 21:12:18)

Посмотрел на это другими глазами. INT0 и INT1 как раз на выходах ШИМ...
А как в баском заставить работать прерывания PCINT3 и PCINT4 - которые на PORTB.3 и PORTB.4?

0

3

Mrshilov написал(а):

Mega48. Как работать с прерываниями PCintX ?

а. направление понял. надо с регистрами поработать ), и с даташитом ), спасибо :)

0

4

vasilii76 написал(а):

А как в баском заставить работать прерывания PCINT3 и PCINT4 - которые на PORTB.3 и PORTB.4

Прерывания INT0, INT1, PCINTx Atmega8_88_328

0

5

sasha_1973 написал(а):

vasilii76 написал(а):

    А как в баском заставить работать прерывания PCINT3 и PCINT4 - которые на PORTB.3 и PORTB.4

Прерывания INT0, INT1, PCINTx Atmega8_88_328

Подпись автора

    "Чем больше узнаешь, тем больше понимаешь, как мало знаешь!" - Сократ

О, шикарный материал!

0

6

При чем в данном случае объявлять

Config INT0
On INT0 Koncevik

не обязательно

Нужно добавить

GIMSK.5 = 1

и проверку нажатой кнопки делать сразу после Powerdown

И у меня вообще сругалось на

Compare0a = 255
Compare0b = 255

Отредактировано SIvan (2013-10-16 22:20:51)

0

7

vasilii76 написал(а):

О, шикарный материал!

Поиск по форуму

http://bascomavr.3bb.ru/search.php?search_id=1389194114

0

8

SIvan написал(а):

и проверку нажатой кнопки делать сразу после Powerdown

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

UPD. понял, кажется. он просыпается по прерыванию, проверяет входы и уходит в подпрограмму. вроде бы так.

Отредактировано vasilii76 (2013-10-17 11:10:31)

0

9

Переписал код с учетом пожеланий выше. Но баг остался. Проблема в том, что когда исполнение программы уходит в подпрограмму (Gosub Main), микроконтроллер успевает уснуть. И именно это мне не очень понятно. Каким образом я это вычислил. В основном цикле закоментил Powerdown ('Powerdown), все работает четко. Как сделать так, чтобы МК не уходил в сон во время выполнения подпрограммы?
То, что получилось:

Код:
$regfile = "attiny13.dat"
$crystal = 9600000
$hwstack = 10
$swstack = 20
$framesize = 20

Config Portb.0 = Output : Portb.0 = 0                       'Выход ШИМ, право
Config Portb.1 = Output : Portb.1 = 0                       'Выход ШИМ, лево
Config Portb.2 = Output : Portb.2 = 0
Config Portb.3 = Input : Portb.3 = 1                        'Вход концевик, лево
Config Portb.4 = Input : Portb.4 = 1                        'Вход концевик, право

Rkon Alias Pinb.4
Lkon Alias Pinb.3
Rlamp Alias Compare0a
Llamp Alias Compare0b

Config Timer0 = Pwm , Compare A = Clear , Compare B = Clear , Prescale = 1


 Sreg = &B10000000                                          'глобально включаем прерывания
Pcmsk = &B00011000                                          'порты, на которым ловим прерывания
Gimsk = &B00100000                                          'включаем PCINT


Dim A As Byte
Dim L As Byte
Dim L1 As Byte
Dim R As Byte
Dim R1 As Byte
Dim Delay_up As Byte
Dim Delay_down As Byte
Dim Step_l As Byte
Dim Step_r As Byte
Dim N As Byte
Dim M As Byte

'Declare Sub Main
Declare Sub L_pwm_up
Declare Sub R_pwm_up
Declare Sub L_pwm_down
Declare Sub R_pwm_down

A = 0
Delay_up = 1
Delay_down = 2


 Llamp = 255
 Rlamp = 255
Do
' Idle
 If Rkon = 0 Or Lkon = 0 Then Gosub Main
' If Rkon = 0 Then Gosub Main
' If Lkon = 0 Then Gosub Main

Loop
End                                                         'end program

'Koncevik:
' If Rkon = 0 Then Call Main
' If Lkon = 0 Then Call Main
' If Rkon = 0 Or Lkon = 0 Then Call Main
' Gifr = 64

Return

Main:
'Sub Main
 R1 = 0
 L1 = 0
  Do
    If Rkon = 0 And Rlamp = 255 Then Call R_pwm_up
    If Lkon = 0 And Llamp = 255 Then Call L_pwm_up

    If Rkon = 1 And Rlamp = 0 Then Call R_pwm_down
    If Lkon = 1 And Llamp = 0 Then Call L_pwm_down

    If Rkon = 1 And Lkon = 1 Then Exit Do
  Loop
'  R1 = 0 : Rlamp = 255
'  L1 = 0 : Llamp = 255
' End Sub Main
 Gifr = &B00100000
Return

Sub R_pwm_up
   R1 = 1
    For R = 255 To 0 Step -1
      Rlamp = R
      Waitms Delay_up
    Next R
End Sub R_pwm_up

Sub L_pwm_up
   L1 = 1
    For L = 255 To 0 Step -1
      Llamp = L
      Waitms Delay_up
    Next L
End Sub L_pwm_up


Sub R_pwm_down
   R1 = 1
   For R = 0 To 255 Step 1
     Rlamp = R
     Waitms Delay_down
   Next R
End Sub R_pwm_down

Sub L_pwm_down
   L1 = 0
   For L = 0 To 255 Step 1
     Llamp = L
     Waitms Delay_down
   Next L
End Sub L_pwm_down

Отредактировано vasilii76 (2013-10-17 14:42:03)

0

10

Откажитесь от Sub.

"Подпрограммы" вынесите ниже основного цикла:

R_pwm_up:
...
...
Return

R_pwm_down:
...
...
Return

И вызывайте их Gosub R_pwm_up

0

11

SIvan
Еще немного пораскинул мозгами, появилось предположение, что проблема может крыться вот тут:

Do
    If Rkon = 0 And Rlamp = 255 Then Call R_pwm_up
    If Lkon = 0 And Llamp = 255 Then Call L_pwm_up

    If Rkon = 1 And Rlamp = 0 Then Call R_pwm_down
    If Lkon = 1 And Llamp = 0 Then Call L_pwm_down

    If Rkon = 1 And Lkon = 1 Then Exit Do
  Loop

А именно, в последней проверке. Допустим, кнопка отпускается в том момент, когда Rlamp или Llamp горит в полный накал. И в этот же момент происходит проверка:

If Rkon = 1 And Lkon = 1 Then Exit Do

И программа выходит из петли, не отправив тушить лампу в соответствующую подпрограмму.

0

12

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

большое спасибо всем, кто принял участие в наставлении меня на путь правильный :)

Отредактировано vasilii76 (2013-10-18 23:11:45)

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Зависает МК при работе в подпрограмме, вызываемой по прерыванию.