BASCOM AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 329
Зарегистрирован: Пн фев 18, 2008 17:48:40

Сообщение Stass48 »

Добрый вечер!
Напишите как правильно в Баскоме использовать АЦП с режимом Noise Canceler?
Просьба не тыкать в мануалы, даташит и книги. Смотрел, искал, читал. Но ничего не понял. Лучше код с объяснением что, почему и как.
Спасибо.
The only one thing necessary for the triumph of evil ...is for good people to do nothing.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 329
Зарегистрирован: Пн фев 18, 2008 17:48:40

Сообщение Stass48 »

Неужели никто не хочет помочь?
Что не так в этом коде? Что я делаю не так:

Код: Выделить всё

$regfile = "m8adef.dat"
$crystal = 11059200
$baud = 19200

Config Adc = Single , Prescaler = Auto , Reference = Avcc
On Adc Adc_int
Config Portd.2 = Input
Set Portd.2

Dim Vol As Word
Vol = 0

Config Int0 = Falling
On Int0 Button
Enable Interrupts
Enable Int0

Do
Print Vol
Loop

Adc_int:
Vol = Getadc(0)
Config Powermode = Adcnoise
Return

Button:
   Print "Button!"
   Waitms 500
   Gifr = 64
Return

End
?
The only one thing necessary for the triumph of evil ...is for good people to do nothing.
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Stass48 писал(а):Неужели никто не хочет помочь?
А как помочь, если Вы единственный путь отрубили на корню ? :
Stass48 писал(а):Просьба не тыкать в мануалы, даташит и книги.
:dont_know:
Где же ещё искать всю информацию, как не в документации ?
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 329
Зарегистрирован: Пн фев 18, 2008 17:48:40

Сообщение Stass48 »

Простите, а как еще можно объяснить когда это все уже пересмотрел, но все равно ничего не понятно?
Вот нашел код на забугорном сайте, вроде работает... Я его немного переделал.
Вот оригинал:

Код: Выделить всё

'                  ADC_INT.BAS
'  demonstration of GETADC() function in combintion with the idle mode
'  for a better noise immunity
'  Getadc() will also work for other AVR chips that have an ADC converter
'--------------------------------------------------------------------
$regfile = "4433def.dat"
$crystal = 4000000
$baud = 19200
'configure single mode and auto prescaler setting
'The single mode must be used with the GETADC() function
 
'The prescaler divides the internal clock by 2,4,8,15,32,64 or 128
'Because the ADC needs a clock from 50-200 KHz
'The AUTO feature, will select the highest clockrate possible
Config Adc = Single , Prescaler = Auto
'Now give power to the chip
On Adc Adc_isr Nosave
Enable Adc
Enable Interrupts
 
 
 
Dim W As Word , Channel As Byte
 
Channel = 0
'now read A/D value from channel 0
Do
  Channel = 0
  'idle will put the micro into sleep.
  'an interrupt will wake the micro.
  Start Adc
  Idle
  Stop Adc
 
  Print "Channel " ; Channel ; " value " ; W
  Waitms 500
Loop
End
 
Adc_isr:
  push r24
  in r24,sreg
  push r24
  push r25
  W = Getadc(channel)
  pop r25
  pop r24
  !out sreg,r24
  pop r24
Return
'The new M163 has options for the reference voltage
'For this chip you can use the additional param :
'Config Adc = Single , Prescaler = Auto, Reference = Internal
'The reference param may be :
'OFF      : AREF, internal reference turned off
'AVCC     : AVCC, with external capacitor at AREF pin
'INTERNAL : Internal 2.56 voltage reference with external capacitor ar AREF pin
 
'Using the additional param on chip that do not have the internal reference will have no effect.
Вот моя переделка:

Код: Выделить всё

$regfile = "m8adef.dat"
$crystal = 11059200
$baud = 19200

Config Adc = Single , Prescaler = Auto , Reference = Avcc
On Adc Adc_int Nosave
Enable Adc
Enable Interrupts

Dim Vol As Word

Do

  Start Adc
  Config Powermode = Adcnoise
  Stop Adc

  Print Vol
  Waitms 500

Loop

Adc_int:
  push r24
  in r24,sreg
  push r24
  push r25
  Vol = Getadc(0)
  pop r25
  pop r24
  !out sreg,r24
  pop r24
Return

End
Прошил - работает, но:
1) То, что оно работает - вовсе не факт что правильно!
2) Я понятия не имею что происходит в этом коде!

Вот и прошу поэтому помощи в том, в чем не в состоянии разобраться сам. Уж простите, если что не так сказал... :)
The only one thing necessary for the triumph of evil ...is for good people to do nothing.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 9189
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

Эх....
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 329
Зарегистрирован: Пн фев 18, 2008 17:48:40

Сообщение Stass48 »

Roman.com, да вот, пока ждал ответа от "добрых людей" уже сам накатал код и этот код работает. Благо нашел таки папку с примерами в Баскоме (как оказалось, она находится в папке "мои документы", а не в самой папке со средой). Кстати в этой теме по идее должны "обитать" люди, которые знают Баском :wink: Просто эти люди наверное думают что пришел я тут, "халявщик", не хочу напрягаться, а типа "напишите мне код"... И фиг ты им докажешь что уже долбаюсь с этим около 12 часов: изучаю, ищу, пытаюсь разобраться и все тщетно. Вы ведь сами свидетель)) И отчасти эти люди еще забывают о том что очевидные для них вещи, для меня - темный лес и забывают наверное что сами тоже с чего-то начинали и чего-то не понимали и как было трудно разобраться... Но, все же надеюсь что они изменят свое мнение и помогут мне во всем разобраться :))

Вот этот мой код, который работает:
Спойлер

Код: Выделить всё

$regfile = "m8adef.dat"
$crystal = 11059200
$baud = 19200

Config Portd.2 = Input
Set Portd.2

Config Int0 = Falling
On Int0 Mode_sub
Enable Int0

Config Adc = Single , Prescaler = Auto , Reference = Avcc
On Adc Get_adc
Enable Adc

Dim Vol As Word , Vol_buff As Word
Dim Round_pl As Word , Round_min As Word , Round_val As Byte

Vol = 0
Vol_buff = 0
Round_val = 1

Enable Interrupts

Do
   Start Adc
   Config Powermode = Adcnoise
   Stop Adc

   Round_pl = Vol + Round_val
   Round_min = Vol - Round_val

   If Vol <> Vol_buff And Round_pl <> Vol_buff And Round_min <> Vol_buff Then
      Vol_buff = Vol
      Print Vol
      Waitms 100
   End If
Loop

Mode_sub:
   Print "ch_mode"
   Waitms 500
   Gifr = 64
Return

Get_adc:
   Vol = Getadc(0)
Return

End
Но, повторюсь: то, что он просто работает меня не очень устраивает. Мне нужно чтобы он работал ПРАВИЛЬНО (имеется ввиду - по всем "канонам" AVR "библии", так то он и так работает с виду правильно и стабильно, то есть нареканий и конкретных претензий к своему коду я не имею)!

Для удобства выкладываю код из этого файла-примера:
Спойлер

Код: Выделить всё

'--------------------------------------------------------------------
'                  ADC_INT.BAS
'  demonstration of GETADC() function in combintion with the idle mode
'  for a better noise immunity
'  Getadc() will also work for other AVR chips that have an ADC converter
'--------------------------------------------------------------------
$regfile = "m88def.dat"
$crystal = 8000000
$baud = 19200

$hwstack = 40
$swstack = 8
$framesize = 40

Declare Sub Adc_isr()
'configure single mode and auto prescaler setting
'The single mode must be used with the GETADC() function

'The prescaler divides the internal clock by 2,4,8,16,32,64 or 128
'Because the ADC needs a clock from 50-200 KHz
'The AUTO feature, will select the highest clockrate possible
Config Adc = Free , Prescaler = Auto , Reference = Internal
'Now give power to the chip
On Adc Adc_isr Nosave
Enable Adc
Enable Interrupts

Dim W As Word , Channel As Byte

Channel = 0
'now read A/D value from channel 0
Do
  Channel = 0
  'idle will put the micro into sleep.
  'an interrupt will wake the micro.
  Start Adc
  Idle
  Stop Adc

  Print "Channel " ; Channel ; " value " ; W
Loop
End

Sub Adc_isr()
  $asm
    push r26
    push r27
    push r24
    in r24,SREG
    push r24
    push r25
  $end Asm

  W = Getadc(channel)

  $asm
    pop r25
    pop r24
    Out Sreg , R24
    pop r24

    pop r27
    pop r26
  $end Asm

End Sub
Теперь конкретно что меня смущает (в сравнении своего кода и примера из Bascom "ADC_INT.BAS"):
1) Первое что бросается в глаза это строчка: Declare Sub Adc_isr(). На мой взгляд, нет никакой разницы объявлять так официально функцию или просто сделать как сделал я... Я прав?
2) Само название функции. В конце названия: _isr и, как мне показалось это и подсветило название функции розовенькой в коде. Так это влияет на что-то или нет? В помощи по Баскому пишут пример My_isr, что и наводит на всякие подозрения.
3) Присутствие в строке: On Adc Adc_isr Nosave слова Nosave. Как я понял, это слово отвечает за сохранение (а точнее - несохранение) каких-то регистров во время прерывания. Но ЗАЧЕМ здесь это надо? В своем коде, как можно увидеть, я этого слова не использовал... А надо ли?
4) В примере кода от Bascom, сам АЦП конфигурируют как Config Adc = Free, я же конфигурирую его как Config Adc = Single! Влияет ли это на что-то в дальнейшем коде? Или все верно?
5) В примере кода от Bascom, процессор микроконтроллера выключают командой Idle. Почитав литературу, я сделал вывод (могу и ошибаться), что лучше вместо Idle использовать команду Power adcnoise, вроде это должно дать лучшее гашение шумов. Однако в помощи по Баском-у пишут: THIS STATEMENT IS NOT RECOMMENDED. Please use CONFIG POWERMODE instead.. Поэтому я использовал вместо команды Idle - команду CONFIG POWERMODE = adcnoise. Правильно я поступил или нет? Эта строка здесь правильно используется?
6) Ну и наконец, в примере от Баском-а мы видим в коде прерывания АЦП - Ассемблерные вставки, которые, как я понял, сохраняют какие-то регистры, а потом опять их считывают это, как я понял, связано как-то со словом Nosave, о котором я писал в пункте 3. Что это за регистры? За что они отвечают? Что вообще делается при помощи того кода на ассемблере? Зачем этим регистрам сначала приказывают не сохраняться при помощи слова Nosave, а потом пытаются их сохранить при помощи Ассемблерного кода?

На что вообще влияют эти все данные отличия? Ведь мой код тоже работает! Или это все на точность как раз и влияет?

В общем, надеюсь на то что кто-то сможет ответить мне по каждому пункту и разъяснить ситуацию.
roman.com писал(а):Ух... вот бы с удовольствием помог хорошему Человеку...
Огромное Вам Человеческое Благодарю, за Вашу помощь в другой ветке :) И так многое прояснил для себя благодаря Вам! :beer:
The only one thing necessary for the triumph of evil ...is for good people to do nothing.
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Ср авг 26, 2009 08:24:50
Откуда: 1300км от Пупа

Сообщение kip96 »

Найдите в сети книгу Евстифеева Микроконтроллеры авр семейства мега. Там всё популярно расписано. Баском поддерживает управление регистрами напрямую. Найдёте в книге регистр какой надо и включите\выключите его.
Ну или в даташите найдите регистр.
SMCR=&b00000011
sleep
всё просто.
Все делают ошибки, только мудрецы - новые, а дураки - старые.
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Ср авг 26, 2009 08:24:50
Откуда: 1300км от Пупа

Сообщение kip96 »

При прерывании теряете все переменные(данные), по этому Баском сохраняет все регистры. Это занимает много памяти и времени.Что бы сократить объём и увеличить быстродействие, можно самому сохранять именно те регистры, которые нужны. Для этого и командуем баскому не сохранять все.(Nosave)
Короче, если Вы просто считываете АЦП и тут-же выводите их, вам нечего сохранять. А если Вы будете усреднять, то переменную, куда всё складываете, нужно сохранять перед прерыванием.
По 4 пункту уж столько в сети писано переписано, что аж тыкать лень.
Последний раз редактировалось kip96 Сб авг 20, 2016 16:43:25, всего редактировалось 1 раз.
Все делают ошибки, только мудрецы - новые, а дураки - старые.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

kip96 писал(а):При прерывании теряете все переменные(данные)
Ну все же не совсем так. В обработчике прерывания регистры общего назначения могут использоваться под свои нужды, и может случиться так, что будут затерты нужные данные, включая статусный регистр SREG. Потому SREG и все РОН сохраняются в стек в самом начале обработчика, и извлекаются из стека в конце оного.

При Nosave не сохраняется ничего. И тогда уже на программисте лежит обязанность сохранить и извлечь нужное.

Код: Выделить всё

 $asm
    push r26
    push r27
    push r24
    in r24,SREG
    push r24
    push r25
  $end Asm

 .........

  $asm
    pop r25
    pop r24
    Out Sreg , R24
    pop r24

    pop r27
    pop r26
  $end Asm
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Ср авг 26, 2009 08:24:50
Откуда: 1300км от Пупа

Сообщение kip96 »

А остальное всё так?
Все делают ошибки, только мудрецы - новые, а дураки - старые.
Друг Кота
Аватара пользователя
Сообщения: 6323
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

edm2007 писал(а): все РОН сохраняются в стек
Точнее, все РОН, используемые в данном обработчике . Уж такой я буквоед ...
Изображение
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Jack_A писал(а):Точнее, все РОН, используемые в данном обработчике . Уж такой я буквоед ...
Ну это да, такие важные мелочи упускать нельзя. :tea:

Но знаете что интересно? Вот такой код, например:

Код: Выделить всё

$regfile = "m8def.dat"
$crystal = 4000000

Config Int0 = Falling
On Int0 Button

Enable Interrupts
Enable Int0

'------------------------------------------

Do

Loop

'------------------------------------------

Button:

Return
Интересно во что дизассамблируется? А вот в такое (кликабельно):

Изображение

Это версия 1.11.9.8. Может в свежих все лучше? Я давно в баскоме не пишу, но в старых версиях без Nosave всегда сохраняются эти регистры, даже если обработчик совершенно пустой. Вот уже рабочий код динамической индикации:

Изображение

Такие дела. :solder:
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6323
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

edm2007 писал(а): без Nosave всегда сохраняются эти регистры, даже если обработчик совершенно пустой.
Ну так за одно это всякие тому подобные компиляторы, генерящие бездумную кучу кода, стоит заткнуть в одно место. Ну если только новичку помигать диодами. Страшно представить, если на таком @#$% напишут что-то вроде защиты ЛЭП или самозапуска электродвигателя . Я так думаю.
Изображение
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Я ведь не просто так писал про все регистры, применительно к баскому. И это правда грустно. :solder:
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт ноя 06, 2012 12:37:08
Откуда: СПб

Сообщение Мурлокотам »

Это действительно весьма неудобно и печально. Выход один - обязательно вставлять Nosave, а потом вручную сохранять нужные регистры. В хелпе, кстати, это описано.
When you omit NOSAVE all used registers will be saved. These are SREG , R31 to R16 and R11 to R0 with exception of R6,R8 and R9 .

R12 – R15 are not saved.
Лом - это сложное техническое устройство.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Угу. Но это либо весь обработчик на асме писать, либо дизасмить и смотреть что юзается. И кто из пищущих на бейсике это будет делать? :tea:
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Вымогатель припоя
Сообщения: 546
Зарегистрирован: Вс дек 30, 2012 00:32:06
Откуда: Николаев / Украина

Сообщение forfrends »

Друзья, нужна ваша помощь. Пытаюсь сделать таймер на Attiny2313 и DS1307. Пример брал здесь: http://cxem.net/mc/mc168.php
Для пробы взял код из примера, выкинул обработку кнопок, подключил диод и поставил условие: если секунды = 5 то включить светодиод, иначе выключить.
Код программы:
Спойлер

Код: Выделить всё

$regfile = "attiny2313.dat"
$crystal = 8000000

Dim Mine As Byte
Dim Hour As Byte
Dim Seco As Byte

Config Portb.0 = Output ' подключен светодиод

Config Sda = Portd.5  ' подключение DS1307
Config Scl = Portd.4

Config Pind.0 = Input
Config Pind.1 = Input
Pinb.0 = 1

Hour = 0
Mine = 0

Do
   I2cstart
   I2cwbyte &HD0
   I2cwbyte &H00
   I2cstart
   I2cwbyte &HD1
   I2crbyte Seco , Ack
   I2crbyte Mine , Ack
   I2crbyte Hour , Nack
   I2cstop
   Seco = Makedec(seco)
   Mine = Makedec(mine)
   Hour = Makedec(hour)

   If Seco = 5 Then
      Pinb.0 = 0
   Else
      Pinb.0 = 1
   End If

   Waitms 100
Loop
End
Но вместо того что бы быть выключенным, загореться на 5-й секунде, и опять выключиться, светодиод постоянно моргает. В чем ошибка?
Прикрепляю проэкт в Протеусе
Вложения
New Project.rar
(7.03 КБ) 210 скачиваний
Сделать своими руками всегда интересней чем просто купить и пользоваться
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Здравствуйте.

Вам срочно нужно почитать о регистрах DDR, PORT и PIN. Если же Вам просто нужно чтобы работало, то измените PINB.0 на PORTB.0.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Вымогатель припоя
Сообщения: 546
Зарегистрирован: Вс дек 30, 2012 00:32:06
Откуда: Николаев / Украина

Сообщение forfrends »

Да, точно, перепутал Portb.0 и Pinb.0. поменял местами - сразу все заработало! Что-то я не внимательно программу писал..
Сделать своими руками всегда интересней чем просто купить и пользоваться
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт май 03, 2011 10:13:12
Откуда: Россия, Татарстан

Сообщение Tankor »

Народ! Выручайте. ВОт, наваял такое.
Изображение
Изображение
Поскольку разработка велась на макете, где была эмуляция ключей (полевик) и т.д., реалии выявили проблему просыпания из сна. Сразу после ухода пару раз просыпается, а бывает и нет, т.е. не ясно зависание или не выходит из сна. Теперь это стал спаянный реальный макет, на котором буду допиливать. Прошу взглянуть, может где косяк, про который не знаю.
Подпрограмма счётчик засыпания:

Код: Выделить всё

Chek1:
   !lds r16,{Sleep_byte}                                    'If Sleep_byte = 1 Then Goto Sleep_call
   !cpi r16,1
   !brne tm101
   !ldi ZL , low(Sleep_call)                                ' Забираем адрес метки
   !ldi ZH , high(Sleep_call)                               ' Забираем адрес метки
   !ijmp                                                    ' Переход на метку без последствий для стека
Tm101:
Return
Далее уходим на метку Slee_call (это не подпрограмма):

Код: Выделить всё

Sleep_call:
   Set Pwr_on1                                              'выключаем дисплей
   Set Pwr_on                                                'выключаем RTC (время)
   Stop Timer2                                              '
   Config Timer2 = Counter , Async = On , Prescale = 1024 '(переконфигурируем Timer2 на переполнение 9сек)
   Start Timer2
   Do
      Gosub Chek                                           'Обработчик прерывания
      !SBIC pina,7                                          'Проверка подключения зарядки
      !jmp k1
      !lds r16,{Ok_key}                                     'Просыпаемся от нажатия комбинации клавишь (up_key и ok_key)
      !lds r17,{Up_key}                                      'Кнопки завязаны с INT0 и INT1
      !cpi r16,0
      !brne s1
      !cpi r17,0
      !brne s1
      K1:
         Gosub Wake_up                                       'Подпрограмма просыпания
         !ldi r16,1
         !sts {ok_key},r16
         !sts {up_key},r16
         !jmp Main                                                 ' УХОД В ГЛАВНОЕ, НАЧАЛЬНОЕ ОКНО ПРОГРАММЫ (НАЧАЛО)
      S1:                                                   'End If
         !ldi r16,1
         !sts {ok_key},r16
         !sts {up_key},r16
         Power Powersave
         Loop
Ну, и далее подпрограмма просыпания

Код: Выделить всё

Wake_up:                                                    'Тут мы просыпаемся
   Waitms 1
   Reset Pwr_on1                                            'Включаем питание дисплея
   Reset Pwr_on                                             'Включаем питание RTC
   Waitms 1
   Config Graphlcd = Custom , Cols = 128 , Rows = 64 , Lcdname = "SSD1306"
   Lcd_auto = 0
   Initlcd                                                  'Инициализируем LCD
   Waitms 300
    Stop Timer2
    Config Timer2 = Timer , Async = On , Prescale = 64 '(переконфигурируем Timer2 на переполнение 0.5сек)
    Start Timer2
Return
Где-то сидит засада, а понять не могу. Не стабильное просыпание. Прошу помощи.
Проект и схема на скрепке.
Вложения
1.rar
(35.66 КБ) 184 скачивания
Ответить

Вернуться в «AVR»