wip i2c with aht20

This commit is contained in:
hugo LAMY
2025-03-16 16:56:08 +01:00
parent 986efac082
commit 35582f4286
3 changed files with 415 additions and 66 deletions

View File

@@ -25,6 +25,7 @@ void print_hex_value(char c);
// i2c.c // i2c.c
void i2c_init(void); void i2c_init(void);
void i2c_start(void); void i2c_start(void);
void i2c_start_repeat(void);
void i2c_send_addr_w(uint8_t slave_address); void i2c_send_addr_w(uint8_t slave_address);
void i2c_send_addr_r(uint8_t slave_address); void i2c_send_addr_r(uint8_t slave_address);
void i2c_write(unsigned char data); void i2c_write(unsigned char data);

View File

@@ -14,15 +14,19 @@ void i2c_init(void) {
TWBR = ((F_CPU / TWI_FREQ) - 16) / (2 * TWI_PRESCALE_VALUE); // 22.9.1 : (Bit Rate Register) set SCL frequency (formula from datasheet, 22.5.2) TWBR = ((F_CPU / TWI_FREQ) - 16) / (2 * TWI_PRESCALE_VALUE); // 22.9.1 : (Bit Rate Register) set SCL frequency (formula from datasheet, 22.5.2)
} }
void i2c_start_repeat(void) { // 22.7.1 : "Repeated START enables the Master to switch between Slaves, Master Transmitter mode and Master Receiver mode without losing control of the bus"
i2c_start();
}
void i2c_start(void) { void i2c_start(void) {
i2c_status = START; 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 = SEND_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))); // p225 example code : Wait for TWINT Flag set. This indicates that the START condition has been transmitted 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 // uint8_t status = TWSR & 0b11111000; // Table 22-2. Status codes for Master Transmitter Mode
if (status != TW_START && status != TW_REP_START) { // if (status != TW_START && status != TW_REP_START) {
return i2c_stop(); // return i2c_stop();
} // }
} }
void i2c_send_addr_w(uint8_t slave_address) { void i2c_send_addr_w(uint8_t slave_address) {
@@ -34,16 +38,16 @@ void i2c_send_addr_w(uint8_t slave_address) {
TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode 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 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 // 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) // if (status == TW_MT_SLA_ACK) { // status 0x18 : slave address transmitted, slave acknoledged (continue transmission)
return; // return;
} else if (status == TW_MT_SLA_NACK) { // status 0x20 : slave address transmitted, slave did not acknoledge (retry or send STOP) // } else if (status == TW_MT_SLA_NACK) { // status 0x20 : slave address transmitted, slave did not acknoledge (retry or send STOP)
return i2c_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) // } 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(); // return i2c_stop();
} else { // } else {
return i2c_stop(); // return;
} // }
} }
void i2c_send_addr_r(uint8_t slave_address) { void i2c_send_addr_r(uint8_t slave_address) {
@@ -55,16 +59,16 @@ void i2c_send_addr_r(uint8_t slave_address) {
TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode 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 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 // 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) // if (status == TW_MR_SLA_ACK) { // status 0x40 : slave address transmitted, slave acknoledged (continue transmission)
return; // return;
} else if (status == TW_MR_SLA_NACK) { // status 0x48 : slave address transmitted, slave did not acknoledge (retry or send STOP) // } else if (status == TW_MR_SLA_NACK) { // status 0x48 : slave address transmitted, slave did not acknoledge (retry or send STOP)
return i2c_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) // } 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(); // return i2c_stop();
} else { // } else {
return i2c_stop(); // return;
} // }
} }
void i2c_write(unsigned char data) { void i2c_write(unsigned char data) {
@@ -72,13 +76,13 @@ void i2c_write(unsigned char data) {
return; return;
} }
TWDR = data; // 22.9.4 : (Data Register) load data into TWDR register TWDR = data; // 22.9.4 : (Data Register) load data into TWDR register
TWCR = SEND_CONTINUE_TRANSMISSION; // p225 example code : Load DATA into TWDR Register. Clear TWINT bit in TWCR to start transmission of data TWCR = SEND_CONTINUE_TRANSMISSION; // 22.7.1 : Master Transmitter Mode
while (!(TEST(TWCR, TWINT))); // p225 example code : Wait for TWINT Flag set. This indicates that the DATA has been transmitted, and ACK/NACK has been received 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 // uint8_t status = TWSR & 0b11111000; // Table 22-3 : check status for Receiver mode, mask prescaler bits
if (status != TW_MT_DATA_ACK) { // if (status != TW_MT_DATA_ACK) {
return i2c_stop(); // return i2c_stop();
} // }
} }
void i2c_read(void) { void i2c_read(void) {

View File

@@ -1,26 +1,305 @@
#include "header.h" #include "header.h"
// sqtatus codes : /*
// -- Master -- before init : 11111000
// TW_BUS_ERROR 0x00 = 0b0 = 0 -> illegal start or stop condition after init : 11111000
// TW_START 0x08 = 0b1000 = 8 -> start condition transmitted after start : 1000
// TW_REP_START 0x10 = 0b10000 = 16 -> repeated start condition transmitted after SLA+W : 11000
// -- Master Transmitter -- 1 : 11000
// TW_MT_SLA_ACK 0x18 = 0b11000 = 24 -> SLA+W transmitted, ACK received 2 : 11000
// TW_MT_SLA_NACK 0x20 = 0b100000 = 32 -> SLA+W transmitted, NACK received 3 : 11000
// TW_MT_DATA_ACK 0x28 = 0b101000 = 40 -> data transmitted, ACK received 4 : 11000
// TW_MT_DATA_NACK 0x30 = 0b110000 = 48 -> data transmitted, NACK received 5 : 11000
// TW_MT_ARB_LOST 0x38 = 0b111000 = 56 -> arbitration lost in SLA+W or data 6 : 11000
// -- Master Receiver -- 7 : 11000
// TW_MR_ARB_LOST 0x38 = 0b111000 = 56 -> arbitration lost in SLA+R or NACK 8 : 11000
// TW_MR_SLA_ACK 0x40 = 0b1000000 = 64 -> SLA+R transmitted, ACK received 9 : 11000
// TW_MR_SLA_NACK 0x48 = 0b1001000 = 72 -> SLA+R transmitted, NACK received 10 : 11000
// TW_MR_DATA_ACK 0x50 = 0b1010000 = 80 -> data received, ACK returned 20 : 11000
// TW_MR_DATA_NACK 0x58 = 0b1011000 = 88 -> data received, NACK returned 30 : 11000
// TW_ST_SLA_ACK 0xA8 = 0b10101000 = 168 -> SLA+R received, ACK returned 40 : 11000
// TW_NO_INFO 0xF8 = 0b11111000 = 248 -> no state information available 50 : 11000
60 : 11000
70 : 11000
80 : 11000
90 : 11000
100 : 11000
110 : 11000
120 : 11000
130 : 11000
140 : 11000
150 : 11000
160 : 11000
170 : 11000
180 : 11000
190 : 11000
200 : 11000
1200 : 11000
after stop : 11111000
*/
#define SLAVE_ADDRESS 0x38 // doc AHT20, 7.3 : address of thermistor /*
before init : 11111000
after init : 11111000
before start : 11111000
after start : 1000
waiting 200ms... : 1000
done waiting : 1000
send SLA+W : 1000
after SLA+W : 11000
waiting 10ms... : 11000
done waiting : 11000
send 0xAC (trigger measurement) : 11000
after 0xAC : 101000
send parameter 1st byte 0x33 : 101000
after 0x33 : 101000
send parameter 2nd byte 0x00 : 101000
after 0x00 : 101000
status ? 0 : 101000
status ? 10 : 101000
status ? 20 : 101000
status ? 30 : 101000
status ? 40 : 101000
status ? 50 : 101000
status ? 60 : 101000
status ? 70 : 101000
status ? 80 : 101000
status ? 90 : 101000
status ? 100 : 101000
status ? 110 : 101000
status ? 120 : 101000
status ? 130 : 101000
after stop : 11111000
*/
/*
before init : 11111000 no state information available
after init : 11111000
before start : 11111000
after start : 1000 start condition transmitted
waiting 200ms... : 1000
done waiting : 1000
send SLA+W : 1000
after SLA+W : 11000 SLA+W transmitted, ACK received
waiting 10ms... : 11000
done waiting : 11000
send 0xAC (trigger measurement) : 11000
after 0xAC : 101000 data transmitted, ACK received
send parameter 1st byte 0x33 : 101000
after 0x33 : 101000
send parameter 2nd byte 0x00 : 101000
after 0x00 : 101000
send repeat start : 101000
after repeat start : 10000 repeated start condition transmitted
send SLA+R : 10000
after SLA+R : 1000000 SLA+R transmitted, ACK received
status ? 0 : 1000000
status ? 10 : 1000000
status ? 20 : 1000000
status ? 30 : 1000000
status ? 40 : 1000000
status ? 50 : 1000000
status ? 60 : 1000000
status ? 70 : 1000000
status ? 80 : 1000000
status ? 90 : 1000000
status ? 100 : 1000000
status ? 110 : 1000000
status ? 120 : 1000000
status ? 130 : 1000000
after stop : 11111000
*/
/*
before init : 11111000 no state information available
after init : 11111000
before start : 11111000
after start : 1000 start condition transmitted
send 0x71 to get a byte of status word : 1000
after 0x71 : 1000000 SLA+R transmitted, ACK received
waiting 200ms... : 1000000
done waiting : 1000000
send 0x71 to get a byte of status word : 1000000
after 0x71 : 1011000 data received, NACK returned
send SLA+W : 1011000
after SLA+W : 1011000
waiting 10ms... : 1011000
done waiting : 1011000
send 0xAC (trigger measurement) : 1011000
after 0xAC : 11111000 no state information available
send parameter 1st byte 0x33 : 11111000
after 0x33 : 11111000
send parameter 2nd byte 0x00 : 11111000
after 0x00 : 11111000
send repeat start : 11111000
after repeat start : 1000 start condition transmitted
send SLA+R : 1000
after SLA+R : 1000000 SLA+R transmitted, ACK received
status ? 0 : 1000000
status ? 10 : 1000000
status ? 20 : 1000000
status ? 30 : 1000000
status ? 40 : 1000000
status ? 50 : 1000000
status ? 60 : 1000000
status ? 70 : 1000000
status ? 80 : 1000000
status ? 90 : 1000000
status ? 100 : 1000000
status ? 110 : 1000000
status ? 120 : 1000000
status ? 130 : 1000000
after stop : 11111000
*/
/*
init i2c : 11111000 no state information available
after init : 11111000
start transmission : 11111000
after start : 1000 start condition transmitted
send SLA+W : 1000
after SLA+W : 11000 SLA+W transmitted, ACK received
waiting 10ms... : 11000
done waiting : 11000
send 0xAC (trigger measurement) : 11000
after 0xAC : 101000 data transmitted, ACK received
send parameter 1st byte 0x33 : 101000
after 0x33 : 101000
send parameter 2nd byte 0x00 : 101000
after 0x00 : 101000
send repeat start : 101000
after repeat start : 10000 repeated start condition transmitted
send SLA+R : 10000
after SLA+R : 1000000 SLA+R transmitted, ACK received
status ? 0 : 1000000
status ? 10 : 1000000
status ? 20 : 1000000
status ? 30 : 1000000
status ? 40 : 1000000
status ? 50 : 1000000
status ? 60 : 1000000
status ? 70 : 1000000
status ? 80 : 1000000
status ? 90 : 1000000
status ? 100 : 1000000
status ? 110 : 1000000
status ? 120 : 1000000
status ? 130 : 1000000
send stop : 1000000
after stop : 11111000 no state information available
*/
/*
init i2c : 11111000 no state information available
after init : 11111000
start transmission : 11111000
after start : 1000 start condition transmitted
send SLA+W : 1000
after SLA+W : 11000 SLA+W transmitted, ACK received
send 0xAC (trigger measurement) : 11000
after 0xAC : 101000 data transmitted, ACK received
send parameter 1st byte 0x33 : 101000
after 0x33 : 101000
send parameter 2nd byte 0x00 : 101000
after 0x00 : 101000
send repeat start : 101000
after repeat start : 10000 repeated start condition transmitted
send SLA+R : 10000
after SLA+R : 1000000 SLA+R transmitted, ACK received
status ? 0 : 1000000
status ? 10 : 1000000
status ? 20 : 1000000
status ? 30 : 1000000
status ? 40 : 1000000
status ? 50 : 1000000
status ? 60 : 1000000
status ? 70 : 1000000
status ? 80 : 1000000
status ? 90 : 1000000
status ? 100 : 1000000
status ? 110 : 1000000
status ? 120 : 1000000
status ? 130 : 1000000
send stop : 1000000
after stop : 11111000 no state information available
*/
/*
init i2c : 11111000 no state information available
after init : 11111000
start transmission : 11111000
after start : 1000 start condition transmitted
send SLA+W : 1000
after SLA+W : 11000 SLA+W transmitted, ACK received
send 0xAC (trigger measurement) : 11000
after 0xAC : 101000 data transmitted, ACK received
send parameter 1st byte 0x33 : 101000
after 0x33 : 101000
send parameter 2nd byte 0x00 : 101000
after 0x00 : 101000
send SLA+R : 101000
after SLA+R : 110000 data transmitted, NACK received
status ? 0 : 110000
status ? 10 : 110000
status ? 20 : 110000
status ? 30 : 110000
status ? 40 : 110000
status ? 50 : 110000
status ? 60 : 110000
status ? 70 : 110000
status ? 80 : 110000
status ? 90 : 110000
status ? 100 : 110000
status ? 110 : 110000
status ? 120 : 110000
status ? 130 : 110000
send stop : 110000
after stop : 11111000
*/
// status codes :
// -- Master --
// TW_BUS_ERROR 0x00 = 0b0 = 0 -> illegal start or stop condition
// TW_START 0x08 = 0b1000 = 8 -> start condition transmitted
// TW_REP_START 0x10 = 0b10000 = 16 -> repeated start condition transmitted
// -- Master Transmitter --
// TW_MT_SLA_ACK 0x18 = 0b11000 = 24 -> SLA+W transmitted, ACK received
// TW_MT_SLA_NACK 0x20 = 0b100000 = 32 -> SLA+W transmitted, NACK received
// TW_MT_DATA_ACK 0x28 = 0b101000 = 40 -> data transmitted, ACK received
// TW_MT_DATA_NACK 0x30 = 0b110000 = 48 -> data transmitted, NACK received
// TW_MT_ARB_LOST 0x38 = 0b111000 = 56 -> arbitration lost in SLA+W or data
// -- Master Receiver --
// TW_MR_ARB_LOST 0x38 = 0b111000 = 56 -> arbitration lost in SLA+R or NACK
// TW_MR_SLA_ACK 0x40 = 0b1000000 = 64 -> SLA+R transmitted, ACK received
// TW_MR_SLA_NACK 0x48 = 0b1001000 = 72 -> SLA+R transmitted, NACK received
// TW_MR_DATA_ACK 0x50 = 0b1010000 = 80 -> data received, ACK returned
// TW_MR_DATA_NACK 0x58 = 0b1011000 = 88 -> data received, NACK returned
// TW_SR_GCALL_DATA_NACK 0x98 = 0b10011000 = 152 -> general call data received, NACK returned
// 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
void print_hex_value(char c) {} void print_hex_value(char c) {}
@@ -36,33 +315,98 @@ void print_status(char *str) {
int main() { int main() {
uart_init(); uart_init();
print_status("before init"); // 0x18 : 11000 : 24
// 0x33 : 110011 : 51 -> DATA0
// 0x38 : 111000 : 56
// 0x70 : 1110000 : 112 -> SLA+W
// 0x71 : 1110001 : 113 -> SLA+R
//
// doc AHT20 7.4 : trigger measurement data and read temperature and humidity
// 0. init i2c
// 1. after power on, wait >= 100ms
// 2. send SLA+W 0x70
// 3. wait 10ms
// 4. send 0xAC command (172, 0b10101100) (trigger measurement), this command parameter has 2 bytes :
// 5. send DATA0 : 0x33
// 6. send DATA1 : 0x00
// 7. delay >= 80ms (wait for status[7] == 0)
// 8. send SLA+R
// 9. read 6 bytes
// 10. read CRC
print_status("init i2c");
i2c_init(); i2c_init();
print_status("after init"); print_status(" after init");
print_status("\r\nstart transmission");
i2c_start(); i2c_start();
print_status("after start"); print_status(" after start");
// 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(SLAVE_ADDRESS);
print_status("after SLA+W"); print_status(" after SLA+W");
i2c_write('t'); // print_status("\r\nwaiting 10ms...");
print_status("after write t"); // _delay_ms(10);
// print_status(" done waiting");
i2c_write('e'); print_status("\r\nsend 0xAC (trigger measurement)");
print_status("after write e"); i2c_write(0xAC);
print_status(" after 0xAC");
print_status("send parameter 1st byte 0x33");
i2c_write(0x33);
print_status(" after 0x33");
print_status("send parameter 2nd byte 0x00");
i2c_write(0x00);
print_status(" after 0x00");
i2c_write('e'); // print_status("\r\nwaiting 10ms...");
print_status("after write e"); // _delay_ms(10);
// print_status(" done waiting");
i2c_write('a'); print_status("\r\nsend repeat start");
print_status("after write a"); i2c_start_repeat();
print_status(" after repeat start");
i2c_write('t'); print_status("\r\nsend SLA+R");
print_status("after write t"); i2c_send_addr_r(SLAVE_ADDRESS);
print_status(" after SLA+R");
print_status("\r\nstatus ? 0");
_delay_ms(10);
print_status("status ? 10");
_delay_ms(10);
print_status("status ? 20");
_delay_ms(10);
print_status("status ? 30");
_delay_ms(10);
print_status("status ? 40");
_delay_ms(10);
print_status("status ? 50");
_delay_ms(10);
print_status("status ? 60");
_delay_ms(10);
print_status("status ? 70");
_delay_ms(10);
print_status("status ? 80");
_delay_ms(10);
print_status("status ? 90");
_delay_ms(10);
print_status("status ? 100");
_delay_ms(10);
print_status("status ? 110");
_delay_ms(10);
print_status("status ? 120");
_delay_ms(10);
print_status("status ? 130");
print_status("\r\nsend stop");
i2c_stop(); i2c_stop();
print_status("after stop"); print_status(" after stop");
while(1); while(1);
} }