Jump to content
GUM

Проблема с TWI(I2C)

Recommended Posts

Posted (edited)

Всем привет! Начал разбираться с протоколом TWI(I2C) на авр, а именно atmega 8. Почитал статьи на изиэлектроник, написал обработку на прерываниях(подсматривая в пример), чтобы вникнуть. Начал тестить в протеус иии... Неизвестная бага не дает мне покоя. Старт производит, адрес слэйва передает(с битом на запись), адрес нужной ячейки передает, а уже при записи пишет ерунду, все время одно и то же, первый 0x00, второй 0xff, потом стоп(стоп запланирован) и какие бы байты я не писал в обработчике, передает 2 одинаковых 00 и ff... Ошибок не выдает, я поставил флаг на ошибки(1 на ноге), в нужное подпрерывание попадает ровно столько раз, сколько надо(тое ставил флаги туда), да и ставил флаги в другие обработчики прерываний(в которые не надо попадать в данном случае), но все норм. Я скину сюда часть кода, эквиваленты, озу нужные, макрос на отправку, и обработчики прерываний, которые используются для отправки байтов. Пишите, если нужна будет доп информация.

Кстати, все прогнал по трассировщику в студии,  просто сделал rcall на нужную последовательность обработчиков

.equ F_CPU = 8000;частота процессора
    
    
    .equ i2c_sarp   = 0b00000000    // Start-Addr_R-Read-Stop                   Это режим простого чтения. Например из слейва или из епрома с текущего адреса
    .equ i2c_sawp   = 0b10000000            // Start-Addr_W-Write-Stop          Это режим простой записи. 

    .equ i2c_sawsawp    = 0b10000001                // Start-Addr_W-WrPageAdr-Write-Stop    Это режим с предварительной записью нужного адреса страницы в 1 байт  а потом запись
    .equ i2c_saw2sawp       = 0b10000011            // Start-Addr_WrPageAdrH-WrPageAdrL-Write-Stop  Это режим с предварительной записью нужного адреса страницы в 2 байт  а потом запись

    .equ i2c_sawsarp        = 0b00000001            // Start-Addr_W-WrPageAdr-rStart-Addr_R-Read-Stop       Это режим с предварительной записью нужного адреса страницы в 1 байт  а потом чтение
    .equ i2c_saw2sarp       = 0b00000011

 

.DSEG
        
        ;"******" - нужно вносить изменения в основном цикле!!!!!!
        I2C_SlaveAdres: .byte 1;регистр с адресом слэйва******************

        I2C_busy: .byte 1; байт флага занятости шины и2с 1-занято! 0-свободно!
        I2C_ERR: .byte 1;байт для ошибок
        
        I2C_DO: .byte 1;задание, читать или записывать, 2 байта адрес или 1?**********

        I2C_LOW_ADRES: .byte 1;младший байт адреса ячейки для чтения/записи(если адрес однобайтовый, то младший единственный)********
        I2C_HIGH_ADRES: .byte 1;старший байт адреса ячейки для чтения/записи***************

        I2C_KOL_BYTE: .byte 1; сколько байт нужно прочесть или записать? писать количетсво!!!!***********

        I2C_BUFER: .byte 5; байты, которые хотим пропихнуть*************

        I2c_ADRES_BUFER_IN: .byte 2;младший и старший байты адреса начала буфера данных для приема!***************

        I2C_ADRES_BUFER_OUT: .byte 2;младший и старший байты адреса начала буфера данных для отправки!****************

        I2C_INDEX_DATA: .byte 1;размер смещения,т.е. сколько байт уже отправлено, вначале отправки должен ранвться 0!

 

TWSI:;перрывание i2c
PUSHF;р16 и sreg в стэк
PUSH R17;в стек
PUSH R18
PUSH R0;в стек
PUSH R30;в стек
PUSH R31;в стек
CLR R0;нужен 0
LDI ZH,HIGH(TWI_TABLE);заносим в индексную пару адрес таблицы причины прерывания и2с
LDI ZL,LOW(TWI_TABLE);и младший байт
UIN R16,TWSR;кода прерывания в р16
LSR R16;сдвиг влево
LSR R16;еще
LSR R16;и еще
ADD ZL,R16;прибавляем значение к адресу таблицы
ICALL;переходим на причину прерывания


POP R31;достаем из стека z пару
POP R30;
POP R0;р0 из стека
POP R18
POP R17;р17 из стека
POPF;достаем р16 и sreg
RETI;выход из прерывания

TWI_TABLE:;таблица прерываний
RJMP TWI_0x00;0x00 Bus Fail Автобус сломался… эээ в смысле аппаратная ошибка шины. Например, внезапный старт посреди передачи бита.

RJMP TWI_0x08;0x08 Start Был сделан старт. Теперь мы решаем что делать дальше, например послать адрес ведомого

RJMP TWI_0x10;0x10 ReStart Был обнаружен повторный старт. Можно переключиться с записи на чтение или наоборот. От логики зависит.

RJMP TWI_0x18;0x18 SLA+W+ACK Мы отправили адрес с битом записи, а в ответ получили ACK от ведомого. Значит можно продолжать.

RJMP TWI_0x20;0x20 SLA+W+NACK Мы отправили адрес с битом записи, а нас послали NACK. Обидно, сгенерим ошибку или повторим еще раз.

RJMP TWI_0x28;0x28 Byte+ACK Мы послали байт и получили подтверждение, что ведомый его принял. Продолжаем.

RJMP TWI_0x30;0x30 Byte+NACK Мы послали байт, но подтверждение не получили. Видимо ведомый уже сыт по горло нашими подачками или он захлебнулся в данных. 
;Либо его ВНЕЗАПНО посреди передачи данных украли инопланетяне.

RJMP TWI_0x38;0x38 Collision А у нас тут клановые разборки — пришел другой мастер, 
;по хамски нас перебил, да так, что мы от возмущения аж заткнулись. Ничего I’l be back! До встречи через n тактов!

RJMP TWI_0x40;0x40 SLA+R+ACK Послали адрес с битом на чтение, а ведомый отозвался. Хорошо! Будем читать.

RJMP TWI_0x48;0x48 SLA+R+NACK Крикнули в шину «Эй ты, с адресом ХХХ, почитай нам сказки» А в ответ «Иди NACK!» 
;В смысле на запрос адреса с битом чтения никто не откликнулся. Видимо не хотят или заняты. Также может быть никого нет дома.

RJMP TWI_0x50;0x50 Receive Byte Мы приняли байт. И думаем что бы ответить ведомому. ACK или NACK.

RJMP TWI_0x58;0x58 Receive Byte+NACK Мы приняли байт от ведомого и сказали ему «иди NACK!» И он обиженый ушел, освободив шину.

TWI_0x10: ;повторный старт
TWI_0x08:;произвели старт!
LDS R16,I2C_SlaveAdres;адрес слэйва
LDS R17,I2C_DO;что нужно, запись или чтение?
CPI R17,0
BRNE TWI_0x10_WR
ORI R16,1<<0
TWI_0x10_WR:
OUT TWDR,R16;отправляем адрес слейва по шине и2с
OUTI TWCR,0<<TWEA|0<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE|1<<TWINT ;флаг преывания, блок тви и разрешаем прерывания
;TWINT флаг прерывания
;TWEA 1-ACK, 0-NACK
;TWSTA 1-start, 0-no start
;TWSTO 1-stop
;TWEN блок TWI включен
;TWIE - разрешаем прерывания TWI
RET;выход из подпрерывания

 

TWI_0x18:;подтверждение после посылки байта адреса и бита записи
LDS R16,I2C_DO;загружаем тех задание в регистр
SBRS R16,0;проверяем, нужно ли нам только записать байт? если да, то переход БЕЗ АДРЕСОВ!
RJMP TWI_0x18_sawp;чтение тут невозможно! т.к. на чтении будет другое подпрерывание
SBRC R16,0;проверяем, а не нужно ли нам послать адрес ячейки? в которую хотим писать
RJMP TWI_0x18_sawsawp;если нужно , то переход. Адрес ячейки состоит из одного байта! соответственно младшего
;если ничего не подошло, значит нужно отправить адрес состоящий из двух байт
;передачу начинаем со старшего байта, затем просто в тех задании поправим на пересылку оставшегося младшего байта
LDS R17,I2C_HIGH_ADRES;загружаем старший байт
ANDI R16,~(1<<0);обнуляем первый бит тех задания, тем самым переводим его на отправку еще одного байта адреса(младшего)
STS I2C_DO,R16
OUT TWDR,R17;загружаем старший байт адреса в тви
RET;выход из подпрерывания

  

TWI_0x18_sawsawp:;ЭТО КЛОООООН!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Запись только младшего байта адреса
LDS R17,I2C_LOW_ADRES;загружаем младший байт адреса ячейки слейва
DEC R16;первращаем sawsawp/sawsarp в просто в sawp или sarp!!!, т.е. загружаем в задание только запись! нужный байт адреса мы уже отослали! теперь только запись/чтение 
STS I2C_DO,R16 ;закидываем в задания
OUT TWDR,R17;загружаем адрес ячейки в тви для записи
OUTI TWCR,0<<TWEA|0<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE|1<<TWINT; передача младшего байта адреса!
RET;выход из подпрерывания

 

TWI_0x18_sawp:;ЭТО КЛОООООН!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! запись самих байтов

;(сюда я вставлял счетчик, сколько раз здесь бывает процессор, и все сходится)

LDS R16,I2C_KOL_BYTE;считываем, сколько байт нам нужно записать????
LDS R18,I2C_INDEX_DATA;счетчик, сколько байт скинули
CP R16,R18; кончились байты то?
BREQ TWI_0x18_STOP;если да, то переход и СТОП!!!! говорим слейву: хватит братан, но передаем последний байт)
LDS ZL,I2C_ADRES_BUFER_OUT            //младший байт адреса буфера данных озу, откуда брать байты на отправку
LDS ZH,I2C_ADRES_BUFER_OUT+1       //старший байт адреса буфера данных озу, откуда брать байты на отправку
ADD ZL,R18;прибавляем к адресу  количество байт, которые отправили
ADC ZH,R0
INC R18;увеличиваем счетчик на 1
STS I2C_INDEX_DATA,R18;отправляем в озу
LD R17,Z;берем один из.. байтов по адресу индексной пары 

;(сюда я вставлял строчку LDI R17,1    но отправляет в итоге не одни 1, а опять таки 00 и ff)
OUT TWDR,R17;отправляем в регистр для передачи
OUTI TWCR,0<<TWEA|0<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE|1<<TWINT ;передача очередного байта данных!
RET;выход из подпрерывания

 

TWI_0x18_STOP:;СТОПЭ братан слейв,наелся ты байтов, отдохни ЭТО КЛОООН!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
STS I2C_busy,R0;освобождаем линию тви
OUTI TWCR,1<<TWEA|0<<TWSTA|1<<TWSTO|1<<TWEN|1<<TWIE|1<<TWINT ;запись ОКОНЧЕНА!
RET;выход из подпрерывания

TWI_0x28:
LDS R16,I2C_DO;и так, м ыздесь потому что: 1-отправили адрес и нужна запись байтов в ячейки
;2- отправили адрес и нужно чтение и 3 - отправили старший байт памяти, нужно отправить младший.
CPI R16,i2c_sawp;нужна запись?
BREQ TWI_0x18_sawp;переход
SBRC R16,0;нужно записать оставшийся младший байт?
RJMP TWI_0x18_sawsawp;переход!
;а иначе повторный старт!!!!
OUTI TWCR,1<<TWEA|1<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE|1<<TWINT ;повторный старт, т.к. чтение!
RET;выходи из подпрерывания

 

.MACRO I2C_OUT;НУЖНО ПРЕДВАРИТЕЛЬНО ЗАКИНУТЬ ОТПРАВЛЯЕМЫЕ ДАННЫЕ В И2С БУФЕР!!!
    ;0-адрес слейва, младший байт = 0!!!
    ; 1-запись или чтение? если с адресом, то сколькибитный?
    ;2-младший байт адреса регистра слэйва
    ;3-старший байт адреса регистра слейва(если не нужен, то 0)
    ;4-сколько байт нужно записать, прочитать?
    ;5-какая скорость передачи нужна?
    ;6-откуда брать байты?
    CLR R16
    STS I2C_INDEX_DATA,R16
    LDI R16,1
    STS I2C_BUSY,R16
    OuTI I2C_SlaveAdres,@0
    //OUTI TWAR,@0;заружаем адрес слэйва
    
    LDI R16,@1;загружаем задание
    STS I2C_DO,R16
    
    .if @3>0x00
    LDI ZL,LOW(@2);адрес регистра слэйва для приема/передачи
    LDI ZH,HIGH(@3)
    STS I2C_LOW_ADRES,ZL
    STS I2C_HIGH_ADRES,ZH
    .else
    LDI ZL,LOW(@2)
    STS I2C_LOW_ADRES,ZL
    .endif


    LDI R16,@4;загружаем значение количества байт для приема/передачи
    STS I2C_KOL_BYTE,R16
    
    OUTI TWSR,0<<TWPS1|0<<TWPS0;предделитель 1

    LDI R16,((F_CPU/@5)-16)/2;расчетскорости приема/передачи данных
    UOUT TWBR,R16

    LDI ZL,LOW(@6)
    LDI ZH,HIGH(@6)
    STS I2C_ADRES_BUFER_OUT,ZL
    STS I2C_ADRES_BUFER_OUT+1,ZH

    OUTI TWCR,1<<TWINT|1<<TWEA|1<<TWSTA|0<<TWSTO|1<<TWEN|1<<TWIE;запуск! отправляем старт! 
;TWINT флаг прерывания
;TWEA 1-ACK, 0-NACK
;TWSTA 1-start, 0-no start
;TWSTO 1-stop
;TWEN блок TWI включен
;TWIE - разрешаем прерывания TWI
   .ENDM

Тело:

OUTI I2C_BUFER,1
OUTI I2C_BUFER+1,2

I2C_OUT 0xA2,i2c_sawsawp,0x03,0,2,200,I2C_BUFER - сюда больше не вернется

Main:

зацикливание

Rjmp main

П.С. вот что пишет i2c debuger в протеусе: S A2 A 03 A 00 A FF A P

Edited by GUM
Дополнение

Share this post


Link to post
Share on other sites

Новая информация! Запустил отладчик в протеусе конкретно TWI, ошибка следующая, При отправке любого байта сначала пишется строчка [AVR TWI] Initiating data write 0xA2 [U3](я так понял это то, что я отправил в регистр TWDR), затем идет строчка [AVR TWI] Actual data read written 0xA2 [U3] (это то, что отправили слейву в данном случае). После отправки адреса ячейки для записи у меня одна песня играет, сначала идет строчка PC=0x00F2. [AVR TWI] Initiating data write 0x01 [U3], затем PC=0x0210. [AVR TWI] Actual data read written 0x00 [U3] (так записывает первый байт) последующие отправляет одинаково но по другому в отличие только от первого: PC=0x00F2. [AVR TWI] Initiating data write 0x01 [U3], PC=0x0210. [AVR TWI] Actual data read written 0xFF [U3] -второй байт(должен быть 0x01), PC=0x00F2. [AVR TWI] Initiating data write 0x01 [U3], PC=0x0210. [AVR TWI] Actual data read written 0xFF [U3] - третий, такой же четвертый и тд. То есть в регистр записываются нормальные значения, а по итогу отправляет совсем не те байты! Моет кому помогло понять, в чем ошибка... А то уже всю голову сломал! Брал тупо код обработчика прерываний на асме с сайта изиэлектроник, заменив там только макросы, ошибка идентичная! оставил там только свой макрос на отправку.
 

Share this post


Link to post
Share on other sites

И так друзья) спасибо всем откликнувшимся :-D спустя 2 недели мучений, ковыряний протеуса, осмотра всех режимов отладки, все пошаговые и не пошаговые, я следил за состоянием всех регистров, как TWI , так и РОН,  снижал частоту процессора, что только не делал. Заметил, что пока PC крутиться в главном цикле, который зациклен на main, rjmp main, т.е. он ничего не делает, регистр TWDR самостоятельно меняется на 00, а при передаче второго, третьего и тд байтов на FF не заходя в прерывание, и понял, что что-то тут не так! Уже хотел писать код без прерываний, так сказать быдло код, но решил проверить на микросхеме eeprom, о чудо, все работает, передает нужные байты. Тут надо сказать: Братан, а чего ты раньше не пробовал другие микрухи, а яв от пробовал! Т.к. схема связана с часами, то решил заменить на аналог DSхххх не помню точное название и там была та же самая хрень, только вместо первого байта 00 и последующий ff, он передавал немного другие, например первый 0x02, второй и последующие 0x55 , а я программировал на передачу только 0x01. Ясно, микруха фигово реализована в протеусе. Но все же она мне нужна, моя заказанная еще не пришла, стал копать , что же не так? Пробежался по даташиту, не нашел ничего специфического. Решил передавать байты в разные ячейки, скажем 10 раз по 3 байта каждый раз и того 30 ячеек проверю. И наконец-то обнаружил суть проблемы, по неизвестным причинам при первой отправке байта(ов), не важно, отправлять 1 байт или 1000000, возникает моя проблема , первый байт всегда 0х00, а второй и последующие(хоть миллион байтов) 0хff. А при последующей отправке во второй, третий и тд, все работает, как "часы".  Может кто столкнулся с такой проблемой, надеюсь помогу кому в будущем) Тему можно закрывать!

Share this post


Link to post
Share on other sites

Финальные результаты тестирования литиевых батареек FANSO при нормальных условиях

Перед разработчиком устройства, в котором предполагается использование батарейки, всегда стоит задача выбора того или иного бренда. Конечно, наиболее объективный результат по качеству можно получить при реальном тестировании в режиме работы самого устройства. Для того чтобы у разработчиков была некоторая информация о реальных значениях основных параметров ЛХИТ, инженеры компании КОМПЭЛ решили провести серию из трех тестов. Первый тест на постоянный разряд в нормальных климатических условиях, начатый в апреле 2019 г., мы завершили.

Узнать финальный результат тестирования

Клёво!:rolleyes: по ходу большинство пользователей не пишут на ассемблере. Для вас принципиально использовать асм. 

Share this post


Link to post
Share on other sites

Пишут, еще как пишут. Но... не так коряво. Сколько времени надо потратить, чтобы хоть как-то разобраться в этой портянке.:)

Share this post


Link to post
Share on other sites
                     

Видеокурс Работаем с микроконтроллерами STM32G0. Впервые на русском языке.

В цикле видеокурсов по работе с STM32G0 от компании STMicroelectronics показаны архитектура, периферия (особенности процессорного ядра, режимов пониженного питания, векторов прерываний, DMA и мультиплексора DMA, схемы тактирования и сброса, и.т.д.) и даны практические примеры. Материал дает наглядное понимание того, как начать работу на новых микроконтроллерах STM32G0

Подробнее

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By RIMUS1989i
      Здравствуйте. Затеялся собрать анализатор спектра на светодиодах, 20x20 светодиодов, МК ATMEGA328P. 
      Долго ломал голову, как переключать столбцы без использования МК, дабы его не загружать.И вот что у меня получилось. Набросал тестовую прошивку для теста в протеусе. 
      При инилизации подается импульс на вторую ножку U4a, и на предпоследнем столбце.
      Думал сетку сделать на 5 сдвиговых регистрах (как раз 40 сигнальных линий), но боюсь мощности МК не хватит для обработки FFT и вывода на матрицу, будет подвисать.
      Кто что думает по поводу схемы?
      бегущая строка.pdsprj Natali_2012_program.hex
    • By Максим123456789
      делаю диплом, в схеме у меня микроконтроллер PIC16F688 и мне нужно его заменить на ATmega. Не могу найти похожий
    • By Вячеслав_НС
      Здравствуйте ! подскажите , какую лучше библиотеку использовать (и где ее взять) для управления i2c atmega8 в atmel studio 7  .  задача - управлять atmega8 по i2c ,  цап  PCF8591T .
      понимаю , в интернете много примеров и библиотек , но хотелось бы пример максимально простой и точно рабочий . т.к. пока что все мои попытки не привели к успеху ... то Atmel Studio 7 при компиляции ругается на несуществующий файл ( к примеру - "stream.h") при использовании библиотеки i2c , то еще какие то грабли .
    • By Антон Плюшкин
      В общем есть небольшая тривиальная задача - сделать свитюльку. Контроллер управляет светодиодиками, цвета меняются, людишки довольны.
      Схема проста: Attiny44a -> 2n3904 x3 -> RGB-светодиод.
      Собрал, протестил, всё норм, но!
      Как только в коде я использую функцию задержки - _delay_ms (util/delay.h) - контроллер повисает!
      #define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> int main(void) { // Input/Output Ports initialization // Port A initialization // Function: Bit7=Out Bit6=Out Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In DDRA=(1<<DDA7) | (1<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); // State: Bit7=0 Bit6=0 Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); // Port B initialization // Function: Bit3=In Bit2=Out Bit1=In Bit0=In DDRB=(0<<DDB3) | (1<<DDB2) | (0<<DDB1) | (0<<DDB0); // State: Bit3=T Bit2=0 Bit1=T Bit0=T PORTB=(0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 16000,000 kHz // Mode: Phase correct PWM top=0xFF // OC0A output: Non-Inverted PWM // OC0B output: Non-Inverted PWM // Timer Period: 0,031875 ms // Output Pulse(s): // OC0A Period: 0,031875 ms Width: 0 us // OC0B Period: 0,031875 ms Width: 0 us TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (1<<WGM00); TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00); TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 16000,000 kHz // Mode: Ph. correct PWM top=0x00FF // OC1A output: Non-Inverted PWM // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 0,031875 ms // Output Pulse(s): // OC1A Period: 0,031875 ms Width: 0 us // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10); TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0); // Timer/Counter 1 Interrupt(s) initialization TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (0<<OCIE1A) | (0<<TOIE1); // External Interrupt(s) initialization // INT0: Off // Interrupt on any change on pins PCINT0-7: Off // Interrupt on any change on pins PCINT8-11: Off MCUCR=(0<<ISC01) | (0<<ISC00); GIMSK=(0<<INT0) | (0<<PCIE1) | (0<<PCIE0); // USI initialization // Mode: Disabled // Clock source: Register & Counter=no clk. // USI Counter Overflow Interrupt: Off USICR=(0<<USISIE) | (0<<USIOIE) | (0<<USIWM1) | (0<<USIWM0) | (0<<USICS1) | (0<<USICS0) | (0<<USICLK) | (0<<USITC); // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0); ADCSRB=(0<<ACME); // Digital input buffer on AIN0: On // Digital input buffer on AIN1: On DIDR0=(0<<ADC1D) | (0<<ADC2D); // ADC initialization // ADC disabled ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); unsigned char VL_OCR0A = 0, VL_OCR0B = 0, VL_OCR1A = 0; OCR0A = 0; OCR0B = 0; OCR1A = 0; while(1) { _delay_ms( 100 ); VL_OCR0A = VL_OCR0A + 1; VL_OCR0B = VL_OCR0B + 1; VL_OCR1A = VL_OCR1A + 1; if( VL_OCR0A >= 250 ){ VL_OCR0A = 0; } if( VL_OCR0B >= 250 ){ VL_OCR0B = 0; } if( VL_OCR1A >= 250 ){ VL_OCR1A = 0; } OCR0A = VL_OCR0A; OCR0B = VL_OCR0B; OCR1A = VL_OCR1A; } } Т.е. если указать задержку в начале цикла, то светодиод не светится вообще.
      Если задержку убрать - светодиод немного подсвечивает всеми цветами.
      while(1) { _delay_ms( 100 ); // <--- ЗАДЕРЖКА --- VL_OCR0A = VL_OCR0A + 1; VL_OCR0B = VL_OCR0B + 1; VL_OCR1A = VL_OCR1A + 1; if( VL_OCR0A >= 250 ){ VL_OCR0A = 0; } if( VL_OCR0B >= 250 ){ VL_OCR0B = 0; } if( VL_OCR1A >= 250 ){ VL_OCR1A = 0; } OCR0A = VL_OCR0A; OCR0B = VL_OCR0B; OCR1A = VL_OCR1A; } Где я накосячил?
      З.Ы.: Замечаний по поводу оптимизации кода, излишних переменных и п.р. прошу не писать - изощряюсь как могу ибо не пойму почему не работает
    • By LegionKC
      Добрый день.
      Экспериментирую с платой TP4056 и MK ATmega8, конкретнее - пытаюсь собрать простенькое зарядное устройство с выводом параметров при зарядке/разрядке на АЦП МК. Для измерения тока нашел ACS712. Думаю, что получится выводить ток при зарядке (т.е. когда идет питание на TP4056 и нагрузка отключена) и при разрядке (питание выключено, нагрузка подключена). Нагрузка - резистор. Возникла проблема с измерением напряжения на АКБ. Вернее, проблема с отсутствием идей как это сделать. Может какую-нибудь схему делителя напряжения нужно сделать? Прошу помочь советом. Схему из пэинта прилагаю.
      Спасибо.
       

  • Сообщения

    • С каких делов должно вырабатыватся напряжение. Включите двигатель через лампу 100 Ватт и все будет гудддд.
    • Я думаю там написано не 7.5 "кушает" а до 7.5 может обеспечить) Я купил на али на TDA2030 у которого питание по ДШ свыше 20 вольт, а конденсаторы все стоят на 16В. Экономят, так дешевле))  
    • Я только таким и пользуюсь)) А что есть круче?) Зачем? Будет более точное измерение тока, напряжения и сопротивления? На сколько точней? Скорость будет быстрей? Единственное что для конденсаторов/индуктивностей у меня есть отдельный еще... Вообщем видимо зависит от области применения)) Мне для моего хобби ни разу не понадобился более крутой... не знаю зачем может быть нужен... Я думаю после 830 только осцил есть смысл покупать ))
    • судя по всему проц уже давно мертв ?
    • Кто-то может подскажет... Есть усилитель на TPA3116D2. (XH-M543) Сколько он кушает ампер от блока питания? По даташиту заявлено 7.5А, но по входу питания в качестве защиты от переполюсовки стоит диод SS54, а он 5А. Что-то я запутался... Или диод будет кипятиться и сгорит или этот усилитель кушает меньше. Так сколько же это усилитель кушает?
    • Не знаю, что там за уроки, но правильно так: всё, что не ноль, эквивалентно истине. Поэтому (a) и (a != 0) абсолютно эквивалентны в качестве условия в if и других местах, где требуется. Главное, не думать, что истина всегда эквивалентна 1. То есть (PINB & 1) и (PINB & 2) совсем не то же самое, что (PINB & 1) == 1 и (PINB & 2) == 1
    • "Подвесить без ущерба" не получится, но и с другой стороны, врятли твой усилитель выдаёт искажения менее одной тысячной, да и звенит у тебя  какскад именно на Т10.  Интересно, а какой сигнал на выходе этого канала  со стороны нижней полуволны. Такой же как и у "исправного"? Попробуй навесить такой же конденсатор между БК  Т10 у исправного. Как изменится осциллограмма после этого?
×
×
  • Create New...