Форум РадиоКот https://radiokot.ru/forum/ |
|
Работа с TWI на Atmega https://radiokot.ru/forum/viewtopic.php?f=57&t=194534 |
Страница 1 из 1 |
Автор: | Флуоресценция [ Вт авг 13, 2024 15:22:27 ] | ||
Заголовок сообщения: | Работа с TWI на Atmega | ||
Написал простенькую программку, которая перебирает все возможные адреса TWI устройств на шине, если находит, выплёвывает адрес в COM. Сижу уже несколько дней и не понимаю в чем может быть проблема. Стартовый бит отправляется без проблем (я вижу сообщение "START bit transmitted"). Проблема начинается когда мы заходим в функцию write_byte(...). Там почему-то после записи регистров TWDR и TWCR не устанавливается флаг TWINT, и соответственно он зацикливается в while и спамит мне "Wait sending adress byte". Проверил, TWDR и TWCR записываются корректно. Пробовал выставлять задержки (хотя они тут не нужны), тоже ничего. Вообщем много что перепробовал. Дебажил всё в ардуино, потому что проще. Код: #include <Arduino.h>
//Set your needed setttings here long int CPU_freq = 16000000; //Processor frequency of the microcontroller long int FreqI2C = 200000; //Frequency of SCL line "Hz" (The frequency of operation of your connected device) uint16_t twps_reg = 0x00; //TWI prescaler bits //(TWPS = 0x00: freq SCL [30;10^3]KHz) //(TWPS = 0x01: freq SCL [8;10^3]KHz) //(TWPS = 0x02: freq SCL [2;10^3]KHz) //(TWPS = 0x03: freq SCL [0.5;10^3]KHz) //Global Variables volatile uint8_t TWSR_state; bool write = 0; bool read = 1; volatile uint8_t addres_device; //All functions //Initialization of bus I2C void init_TWI(){ int Prescaler; //TWI Prescaler Bits (see Datasheet) switch(twps_reg){ case 0x00: Prescaler = 1; break; case 0x01: Prescaler = 4; break; case 0x02: Prescaler = 16; break; case 0x03: Prescaler = 64; break; default: Serial.println("Check if the register twps_reg is correct"); Prescaler = 1; //default } TWBR = (CPU_freq/FreqI2C - 8)/Prescaler; //TWI Bit Rate Register TWSR = twps_reg; digitalWrite(SDA, 1); //Transfer the SCL and SDA lines to an internal pull-up resistor digitalWrite(SCL, 1); } //Sending start bit bool transfer_start_bit(){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE); //TWI Control Register while (!(TWCR & (1<<TWINT))) Serial.println("Wait sending START bit"); //Waiting for the TWINT bit to be set if ((TWSR_state == 0x08) || (TWSR_state == 0x10)) return 1; return 0; } //Sending SLA+W and data byte bool write_byte(uint8_t byte, bool R_W){ TWDR = (byte << 1) + R_W; //TWI Data Register TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE); while (!(TWCR & (1<<TWINT))) Serial.println("Wait sending address byte"); //Waiting for the TWINT bit to be set if ((TWSR_state == 0x18) || (TWSR_state == 0x28)) return 1; return 0; } //Sending STOP bit void bus_stop(){ TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO); } //Finding the adress of slave uint8_t searching_I2C_device(){ //We are going through all possible addresses for (uint8_t adress = 0x00; adress < 0xFF; adress++){ if (transfer_start_bit() == 1){ if (write_byte(adress, write) == 1) return adress; } bus_stop(); } return 0; } //Timer1_delay void time1_delay(int delay){ //Delay is specified in the number of processor cycles TCCR1A = 0x00; TCNT1 = 0x0000; TCCR1B = (1<<WGM12)|(0<<CS12)|(1<<CS10)|(0<<CS11); OCR1A = delay; TIMSK1 = (1<<OCIE1A); while(TIMSK1 & (1<<OCIE1A)){} } //Read status of TWSR register ISR (TWI_vect){ switch(TWSR & 0xF8){ case 0x00: TWSR_state = 0x00; //Bus error due to an illegal START or STOP condition Serial.println("Bus error due START or STOP condition"); break; //bus_stop(); case 0x08: TWSR_state = 0x08; //A START condition has been tranmitted Serial.println("START bit transmitted"); break; case 0x10: TWSR_state = 0x10; //A repeated START condition has been transmitted Serial.println("Reapeated START bit transmitted"); break; case 0x18: TWSR_state = 0x18; //SLA+W has been transmitted and ACK has been recieved Serial.println("SLA+W transmitted and ACK bit received"); break; case 0x20: TWSR_state = 0x20; //SLA+W has been transmitted and NOT ACK has been recieved Serial.println("SLA+W transmitted and NOT ACK bit received"); break; //bus_stop(); case 0x28: TWSR_state = 0x28; //Data byte has been transmitted and ACK has been recieved Serial.println("Data byte transmitted and ACK bit recieved"); break; case 0x30: TWSR_state = 0x30; //Data byte has been transmitted and NOT ACK has been recieved Serial.println("Data byte transmitted and NOT ACK bit recieved"); break; bus_stop(); case 0xF8: TWSR_state = 0xF8; //No relevant state information available; TWINT = '0' Serial.println("No relevant state information"); break; default: TWSR_state = 0xFF; //Nothing of the above Serial.println("Undefined state 0xFF"); break; } TWCR = 0x00; } //Turn off the Timer1 ISR(TIMER1_COMPA_vect){ cli(); TIMSK1 = (0<<OCIE1A); asm volatile ("nop"); sei(); } //Setup initial parameters void setup() { sei(); Serial.begin(9600); Serial.println("Start finding the adress of VEML6040"); init_TWI(); } void loop() { addres_device = searching_I2C_device(); if(addres_device != 0){ Serial.print("Address of slave is 0x"); Serial.println(searching_I2C_device(), HEX); } else Serial.println("Address of device is not found"); bus_stop(); }
|
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |