diff --git a/headers/i2c.h b/headers/i2c.h index 374c737..b5b0c2e 100644 --- a/headers/i2c.h +++ b/headers/i2c.h @@ -9,10 +9,9 @@ (value) == 64 ? (1<= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') ? ((ch) ^ (1 << 5)) : (ch)) -// boolean -#define TRUE 1 -#define FALSE 0 +// // boolean +// #define TRUE 1 +// #define FALSE 0 + +// +// ENUM +// +typedef enum { + FALSE, + TRUE +} Boolean; #endif // UTILS_H \ No newline at end of file diff --git a/module06/ex01/header.h b/module06/ex01/header.h index 63cc113..315e9b7 100644 --- a/module06/ex01/header.h +++ b/module06/ex01/header.h @@ -16,6 +16,7 @@ // // GLOBAL // +extern volatile uint8_t i2c_data; // // PROTOTYPES @@ -28,8 +29,9 @@ void i2c_start(void); void i2c_start_repeat(void); void i2c_send_addr_w(uint8_t slave_address); void i2c_send_addr_r(uint8_t slave_address); -void i2c_write(unsigned char data); -uint8_t i2c_read(void); +void i2c_write(uint8_t data); +uint8_t i2c_read_ack(void); +uint8_t i2c_read_nack(void); void i2c_stop(void); // uart.c void uart_init(); @@ -42,6 +44,7 @@ uint16_t uart_printstr_itoa_base_endl(uint64_t value, uint8_t base); void int_to_hex_string(uint64_t value, char *out, uint8_t num_digits); void int_to_string_base(uint64_t value, char *buffer, uint8_t base); + // // MACROS // diff --git a/module06/ex01/i2c.c b/module06/ex01/i2c.c index c208e2e..d110e40 100644 --- a/module06/ex01/i2c.c +++ b/module06/ex01/i2c.c @@ -20,88 +20,106 @@ void i2c_start_repeat(void) { // 22.7.1 : "Repeated START enables the void i2c_start(void) { i2c_status = START; - TWCR = SEND_START_CONDITION; // 22.9.2 : (Control Register) send Start condition (22.7.1) ! writting 1 to TWINT clears it (set it to 0) + TWCR = TWI_START_CONDITION; // 22.9.2 : (Control Register) send Start condition (22.7.1) ! writting 1 to TWINT clears it (set it to 0) while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received - // uint8_t status = TWSR & 0b11111000; // Table 22-2. Status codes for Master Transmitter Mode - // if (status != TW_START && status != TW_REP_START) { - // return i2c_stop(); - // } + uint8_t status = TWSR & 0b11111000; // Table 22-2. Status codes for Master Transmitter Mode + if (status != TW_START && status != TW_REP_START) { + return i2c_stop(); + } } void i2c_send_addr_w(uint8_t slave_address) { if (i2c_status == STOP) { return; } - uint8_t addr = (slave_address << 1) | TW_WRITE; // 22.3.3 : address format SLA+R/W - TWDR = addr; // 22.9.4 : (Data Register) load data into TWDR register - TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode - while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received + uint8_t addr = (slave_address << 1) | TW_WRITE; // 22.3.3 : address format SLA+R/W + TWDR = addr; // 22.9.4 : (Data Register) load data into TWDR register + TWCR = TWI_NACKNOWLEDGE; // 22.7.1 : Master Transmitter Mode + while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received - // uint8_t status = TWSR & 0b11111000; // Table 22-2 : check status for Transmitter mode, mask prescaler bits - // if (status == TW_MT_SLA_ACK) { // status 0x18 : slave address transmitted, slave acknoledged (continue transmission) - // return; - // } else if (status == TW_MT_SLA_NACK) { // status 0x20 : slave address transmitted, slave did not acknoledge (retry or send STOP) - // return i2c_stop(); - // } else if (status == TW_MT_ARB_LOST) { // status 0x38 : Arbitration Lost, Another I2C master took control of the bus (wait for bus to be free and retry) - // return i2c_stop(); - // } else { - // return; - // } + uint8_t status = TWSR & 0b11111000; // Table 22-2 : check status for Transmitter mode, mask prescaler bits + if (status == TW_MT_SLA_ACK) { // status 0x18 : slave address transmitted, slave acknoledged (continue transmission) + return; + } else if (status == TW_MT_SLA_NACK) { // status 0x20 : slave address transmitted, slave did not acknoledge (retry or send STOP) + return i2c_stop(); + } else if (status == TW_MT_ARB_LOST) { // status 0x38 : Arbitration Lost, Another I2C master took control of the bus (wait for bus to be free and retry) + return i2c_stop(); + } else { + return; + } } void i2c_send_addr_r(uint8_t slave_address) { if (i2c_status == STOP) { return; } - uint8_t addr = (slave_address << 1) | TW_READ; // 22.3.3 : address format SLA+R/W - TWDR = addr; // 22.9.4 : (Data Register) load data into TWDR register - TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode - while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received + uint8_t addr = (slave_address << 1) | TW_READ; // 22.3.3 : address format SLA+R/W + TWDR = addr; // 22.9.4 : (Data Register) load data into TWDR register + TWCR = TWI_NACKNOWLEDGE; // 22.7.1 : Master Transmitter Mode + while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received - // uint8_t status = TWSR & 0b11111000; // Table 22-3 : check status for Receiver mode, mask prescaler bits - // if (status == TW_MR_SLA_ACK) { // status 0x40 : slave address transmitted, slave acknoledged (continue transmission) - // return; - // } else if (status == TW_MR_SLA_NACK) { // status 0x48 : slave address transmitted, slave did not acknoledge (retry or send STOP) - // return i2c_stop(); - // } else if (status == TW_MR_ARB_LOST) { // status 0x38 : Arbitration Lost, Another I2C master took control of the bus (wait for bus to be free and retry) - // return i2c_stop(); - // } else { - // return; - // } + uint8_t status = TWSR & 0b11111000; // Table 22-3 : check status for Receiver mode, mask prescaler bits + if (status == TW_MR_SLA_ACK) { // status 0x40 : slave address transmitted, slave acknoledged (continue transmission) + return; + } else if (status == TW_MR_SLA_NACK) { // status 0x48 : slave address transmitted, slave did not acknoledge (retry or send STOP) + return i2c_stop(); + } else if (status == TW_MR_ARB_LOST) { // status 0x38 : Arbitration Lost, Another I2C master took control of the bus (wait for bus to be free and retry) + return i2c_stop(); + } else { + return; + } } void i2c_write(uint8_t data) { if (i2c_status == STOP) { return; } - TWDR = data; // 22.9.4 : (Data Register) load data into TWDR register - TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode - while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received + TWDR = data; // 22.9.4 : (Data Register) load data into TWDR register + TWCR = TWI_NACKNOWLEDGE; // 22.7.1 : Master Transmitter Mode + while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received - // uint8_t status = TWSR & 0b11111000; // Table 22-3 : check status for Receiver mode, mask prescaler bits - // if (status != TW_MT_DATA_ACK) { - // return i2c_stop(); - // } + uint8_t status = TWSR & 0b11111000; // Table 22-2 : check status for Transmitter mode, mask prescaler bits + if (status != TW_MT_DATA_ACK) { + return i2c_stop(); + } } -uint8_t i2c_read(void) { +uint8_t i2c_read_ack(void) { if (i2c_status == STOP) { - return; + return 0; } - TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode - while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received + TWCR = TWI_ACKNOWLEDGE; // 22.7.1 : Master Transmitter Mode + while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received - // uint8_t status = TWSR & 0b11111000; // p225 example code : Check status for Receiver mode. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR - // if (status != TW_MT_DATA_ACK) { - // return i2c_stop(); - // } + uint8_t status = TWSR & 0b11111000; // p225 example code : Check status for Receiver mode. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR + if (status != TW_MT_DATA_ACK) { + i2c_stop(); + return 0; + } - return TWDR; // 22.9.4 : (Data Register) load data into TWDR register + return TWDR; // 22.9.4 : (Data Register) load data into TWDR register +} + +uint8_t i2c_read_nack(void) { + if (i2c_status == STOP) { + return 0; + } + + TWCR = TWI_NACKNOWLEDGE; // 22.7.1 : Master Transmitter Mode + while (!(TEST(TWCR, TWINT))); // 22.7.1 : Wait for TWINT Flag set. This indicates that the SLA+R/W has been transmitted, and ACK/NACK has been received + + uint8_t status = TWSR & 0b11111000; // p225 example code : Check status for Receiver mode. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR + if (status != TW_MT_DATA_NACK) { + i2c_stop(); + return 0; + } + + return TWDR; // 22.9.4 : (Data Register) load data into TWDR register } void i2c_stop(void) { - TWCR = SEND_STOP_CONDITION; // 22.9.2 : send stop condition + TWCR = TWI_STOP_CONDITION; // 22.9.2 : send stop condition i2c_status = STOP; } diff --git a/module06/ex01/main.c b/module06/ex01/main.c index 3cd355d..e329d1c 100644 --- a/module06/ex01/main.c +++ b/module06/ex01/main.c @@ -400,7 +400,9 @@ send stop : 1011000 TW_MR_DATA_NACK -> Data recei // TW_ST_SLA_ACK 0xA8 = 0b10101000 = 168 -> SLA+R received, ACK returned // TW_NO_INFO 0xF8 = 0b11111000 = 248 -> no state information available -#define SLAVE_ADDRESS 0x38 // doc AHT20, 7.3 : address of thermistor : 0b111000, 56 +#define AHT20_ADDRESS 0x38 // doc AHT20, 7.3 : address of thermistor : 0b111000, 56 + +// volatile uint8_t i2c_data = 0; void print_hex_value(char c) { char buffer[3] = {0}; @@ -429,8 +431,7 @@ void print_status_meaning(uint16_t status) { } } -void print_status(char *str) { - return; +void _print_status(char *str) { uint8_t status; status = TWSR & 0b11111000; // Table 22-2. Status codes for Master Transmitter Mode uint16_t size = 53; @@ -445,16 +446,73 @@ void print_status(char *str) { print_status_meaning(status); uart_printstr_endl(""); } +void print_status_anyway(char *str) { + _print_status(str); +} +void print_status(char *str) { + _print_status(str); + return; +} + +void print_data() { + uint8_t data; + for (uint8_t i = 0; i < 10; i++) { + data = i2c_read_nack(); + print_hex_value(data); + if (i == 0) { + uart_tx('('); + uart_printstr_itoa_base(data, 2); + uart_tx(')'); + } + if (i < 9) { + uart_tx(' '); + } + } + uart_printstr_endl(""); +} + +Boolean aht20_is_status_ready(void) { + uint8_t status; + + i2c_start(); + i2c_send_addr_w(AHT20_ADDRESS); + // i2c_write(0xAC); + // i2c_write(0x33); + // i2c_write(0x00); + i2c_start_repeat(); + i2c_send_addr_r(AHT20_ADDRESS); + status = i2c_read_nack(); + i2c_stop(); + + uart_printstr("- status : "); + uart_printstr_itoa_base_endl(status, 2); + if (status & 0b10000000) { + return TRUE; + } else { + return FALSE; + } +} + +void aht20_wait_for_status() { + for (uint8_t i = 0; i < 30; i++) { + uart_tx('|'); + if (aht20_is_status_ready()) { + break; + } + _delay_ms(10); + } +} // description int main() { uart_init(); - // 0x18 : 11000 : 24 - // 0x33 : 110011 : 51 -> DATA0 - // 0x38 : 111000 : 56 - // 0x70 : 1110000 : 112 -> SLA+W - // 0x71 : 1110001 : 113 -> SLA+R + // 0x18 : 11000 : 24 + // 0x33 : 110011 : 51 -> DATA0 + // 0x38 : 111000 : 56 + // 0x70 : 1110000 : 112 -> SLA+W + // 0x71 : 1110001 : 113 -> SLA+R + // 0x80 : 10000000 : 128 // // doc AHT20 7.4 : trigger measurement data and read temperature and humidity // 0. init i2c @@ -477,17 +535,19 @@ int main() { i2c_start(); print_status(" after start"); - // print_status("\r\nwaiting 200ms..."); - // _delay_ms(200); - // print_status(" done waiting"); + // aht20_wait_for_status(); + + print_status("\r\nwaiting 200ms..."); + _delay_ms(200); + print_status(" done waiting"); print_status("\r\nsend SLA+W"); - i2c_send_addr_w(SLAVE_ADDRESS); + i2c_send_addr_w(AHT20_ADDRESS); print_status(" after SLA+W"); - // print_status("\r\nwaiting 10ms..."); - // _delay_ms(10); - // print_status(" done waiting"); + print_status("\r\nwaiting 20ms..."); + _delay_ms(20); + print_status(" done waiting"); print_status("\r\nsend 0xAC (trigger measurement)"); i2c_write(0xAC); @@ -499,29 +559,27 @@ int main() { i2c_write(0x00); print_status(" after 0x00"); - // print_status("\r\nwaiting 10ms..."); - // _delay_ms(10); - // print_status(" done waiting"); - - print_status("\r\nsend repeat start"); - i2c_start_repeat(); - print_status(" after repeat start"); - - print_status("\r\nsend SLA+R"); - i2c_send_addr_r(SLAVE_ADDRESS); - print_status(" after SLA+R"); -; - print_status("\r\nbefore read data"); - uint8_t data; for (uint8_t i = 0; i < 10; i++) { - data = i2c_read(); - print_hex_value(data); - if (i < 9) { - uart_tx(' '); - } + // print_status("\r\nwaiting 100ms..."); + // _delay_ms(100); + // print_status(" done waiting"); + + // aht20_wait_for_status(); + + print_status("\r\nsend repeat start"); + i2c_start_repeat(); + print_status(" after repeat start"); + + print_status("\r\nsend SLA+R"); + i2c_send_addr_r(AHT20_ADDRESS); + print_status_anyway(" after SLA+R"); + + print_status("\r\nbefore read data"); + print_data(); + print_status(" after read data"); + + _delay_ms(300); } - uart_printstr_endl(""); - print_status(" after read data"); print_status("\r\nsend stop"); i2c_stop();