Functioning I2C slave data receive
The slave now receives and prints data successfully.
This commit is contained in:
parent
e1c607514b
commit
4e0b810346
@ -1,6 +1,15 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
|
// Heavily inspired by: https://github.com/microchip-pic-avr-examples/avr128db48-bare-metal-twi-mplab/blob/master/twi-client.X/peripherals/TWI/TWI_client.c
|
||||||
|
|
||||||
void init_i2c(void) {
|
void init_i2c(void) {
|
||||||
|
// Pin setup
|
||||||
|
PORTA.DIRSET = PIN2_bm | PIN3_bm;
|
||||||
|
PORTA.PINCTRLUPD = PIN2_bm | PIN3_bm;
|
||||||
|
|
||||||
|
// Enable operating in debug
|
||||||
|
TWI0.DBGCTRL = TWI_DBGRUN_bm;
|
||||||
|
|
||||||
// Initialize the control A register
|
// Initialize the control A register
|
||||||
TWI0.CTRLA = TWI_INPUTLVL_I2C_gc // I2C voltage transition level
|
TWI0.CTRLA = TWI_INPUTLVL_I2C_gc // I2C voltage transition level
|
||||||
| TWI_SDASETUP_4CYC_gc // Four clock cycles setup time
|
| TWI_SDASETUP_4CYC_gc // Four clock cycles setup time
|
||||||
@ -13,20 +22,60 @@ void init_i2c(void) {
|
|||||||
|
|
||||||
// Enable acting as a slave
|
// Enable acting as a slave
|
||||||
TWI0.SCTRLA = TWI_DIEN_bm // Enable data interrupt
|
TWI0.SCTRLA = TWI_DIEN_bm // Enable data interrupt
|
||||||
|
| TWI_APIEN_bm // Enable more interrupts
|
||||||
| TWI_PIEN_bm // Enable stop flag interrupt
|
| TWI_PIEN_bm // Enable stop flag interrupt
|
||||||
| TWI_SMEN_bm // Enable smart mode
|
| PIN2_bm // Respond to all TWI addresses
|
||||||
| TWI_ENABLE_bm // Enable acting as a slave
|
| TWI_ENABLE_bm // Enable acting as a slave
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Figure out which interrupt does what
|
// TODO: Figure out which interrupt does what
|
||||||
|
|
||||||
// Interrupt vector
|
void i2c_write_handler(uint8_t data) {
|
||||||
ISR(TWI0_TWIS_vect) {
|
printf("%u\n", data);
|
||||||
asm('nop');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interrupt vector
|
void i2c_read_handler() {
|
||||||
ISR(TWI0_TWIM_vect) {
|
printf("Master wanted to read.\n");
|
||||||
asm('nop');
|
}
|
||||||
|
|
||||||
|
void i2c_stop_handler() {
|
||||||
|
printf("Stop, I guess\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address received
|
||||||
|
ISR(TWI0_TWIS_vect) {
|
||||||
|
// Check for the data interrupt flag
|
||||||
|
if (TWI0.SSTATUS & TWI_DIF_bm) {
|
||||||
|
uint8_t data = 0;
|
||||||
|
|
||||||
|
if ( ((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0 ) {
|
||||||
|
// Data write Master -> Slave
|
||||||
|
data = TWI0.SDATA;
|
||||||
|
|
||||||
|
// Send the data to the write handler
|
||||||
|
i2c_write_handler(data);
|
||||||
|
} else {
|
||||||
|
// Data read Master <- Slave
|
||||||
|
i2c_read_handler();
|
||||||
|
data = TWI0.SDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acknowledge having received
|
||||||
|
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for address match or STOP
|
||||||
|
if (TWI0.SSTATUS & TWI_APIF_bm) {
|
||||||
|
|
||||||
|
if (TWI0.SSTATUS & TWI_AP_ADR_gc) {
|
||||||
|
// Address match, just send ack
|
||||||
|
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||||
|
} else {
|
||||||
|
// STOP condition received
|
||||||
|
i2c_stop_handler();
|
||||||
|
// Send ACK
|
||||||
|
TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -15,6 +15,8 @@ extern "C" {
|
|||||||
// Include the IO for I2C
|
// Include the IO for I2C
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
#include "uart.h"
|
||||||
|
#include <util/twi.h>
|
||||||
|
|
||||||
// Initialize the I2C bus
|
// Initialize the I2C bus
|
||||||
void init_i2c(void);
|
void init_i2c(void);
|
||||||
|
|||||||
@ -10,14 +10,18 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
#include "i2c.h"
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
init_uart((uint16_t)9600);
|
init_uart((uint16_t)9600);
|
||||||
|
init_i2c();
|
||||||
stdout = &USART_stream;
|
stdout = &USART_stream;
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("Hello, world!\n");
|
printf("\n");
|
||||||
_delay_ms(500);
|
_delay_ms(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,6 +171,9 @@
|
|||||||
<property key="user-pack-device-support" value=""/>
|
<property key="user-pack-device-support" value=""/>
|
||||||
<property key="wpo-lto" value="false"/>
|
<property key="wpo-lto" value="false"/>
|
||||||
</XC8-config-global>
|
</XC8-config-global>
|
||||||
|
<nEdbgTool>
|
||||||
|
<property key="debugoptions.useswbreakpoints" value="true"/>
|
||||||
|
</nEdbgTool>
|
||||||
</conf>
|
</conf>
|
||||||
</confs>
|
</confs>
|
||||||
</configurationDescriptor>
|
</configurationDescriptor>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user