Hallo zusammen,
Ich möchte in eine Projekt den Sensor Mpu6050 verwenden und mit dem
relativ neuen ATtiny817 auswerten. Allerdings gibt es keine fertige
Library, wie bei Arduino. Ich habe ein I2C Programm aus einem anderen
Forum gefunden und zu meinem Programm hinzugefügt
(https://www.avrfreaks.net/comment/2294081).
Dieses Programm hat auch super mit einem angeschlossenen Arduino nano
funktioniert. Ich habe auch ein Programm zum auslesen vom Mpu6050
gefunden, das ohne I2C Library auskommt
(https://www.avrfreaks.net/forum/mpu6050-pure-avr-c-328p-without-library-help-me-please).
Allerdings musste ich einiges ändern, da I2C bei meinem ATtiny sehr
verschieden zu benutzen ist. Wie es aussieht, kann ich auf dem Sensor
schreiben, aber der "Read Interrupt Flag" wird beim Werte lesen nicht
gesetzt und ich hab keine Ahnung warum. Laut Datenblatt ist meine
Datenübertragung richtig.
Das ist mein "TWI_Master.c" File:
1 | #include <avr/io.h>
|
2 | #include "TWI_master.h"
|
3 | #include "UART.h"
|
4 | #include "General.h"
|
5 | void TWI_init()
|
6 | {
|
7 | TWI0.MBAUD = (uint8_t)TWI0_BAUD(100000); // set MBAUD register for 100kHz
|
8 | TWI0.MCTRLA = 1 << TWI_ENABLE_bp /* Enable TWI Master: enabled */
|
9 | | 0 << TWI_QCEN_bp /* Quick Command Enable: disabled */
|
10 | | 0 << TWI_RIEN_bp /* Read Interrupt Enable: disabled */
|
11 | | 1 << TWI_SMEN_bp /* Smart Mode Enable: enabled */
|
12 | | TWI_TIMEOUT_DISABLED_gc /* Bus Timeout Disabled */
|
13 | | 0 << TWI_WIEN_bp; /* Write Interrupt Enable: disabled */
|
14 |
|
15 | TWI0.MCTRLB |= TWI_FLUSH_bm ; /* Purge MADDR and MDATA */
|
16 | TWI0.MSTATUS |= TWI_BUSSTATE_IDLE_gc ; //Force TWI state machine into IDLE state
|
17 | TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm) ;
|
18 | }
|
19 |
|
20 | uint8_t TWI_start(uint8_t deviceAddr)
|
21 | {
|
22 | if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc) //Verify Bus is not busy
|
23 | {
|
24 | TWI0.MCTRLB &= ~(1 << TWI_ACKACT_bp);
|
25 | TWI0.MADDR = deviceAddr ;
|
26 | printString("bw");
|
27 | if (deviceAddr&0x01) {while(!(TWI0.MSTATUS & TWI_RIF_bm));}
|
28 | else {while(!(TWI0.MSTATUS & TWI_WIF_bm));}
|
29 | printString("aw");
|
30 | return 0;
|
31 | }
|
32 | else return 1; //Bus is busy
|
33 | }
|
34 |
|
35 | uint8_t TWI_read(uint8_t ACK) // ACK=1 send ACK ; ACK=0 send NACK
|
36 | {
|
37 |
|
38 | if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc) //Verify Master owns the bus
|
39 | {
|
40 | while(!(TWI0.MSTATUS & TWI_RIF_bm)); // Wait until RIF set
|
41 | uint8_t data=TWI0.MDATA;
|
42 | if (ACK==1) {TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);}
|
43 | else {TWI0.MCTRLB |= (1<<TWI_ACKACT_bp); }
|
44 | USART_write((uint8_t)data);
|
45 | return data ;
|
46 | }
|
47 | else
|
48 | return 1; //Master does not own the bus
|
49 |
|
50 | }
|
51 | uint8_t TWI_WRITE(uint8_t write_data)
|
52 | {
|
53 | if ((TWI0.MSTATUS&TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc) //Verify Master owns the bus
|
54 | {
|
55 | TWI0.MDATA = write_data;
|
56 | while (!((TWI0.MSTATUS & TWI_WIF_bm) | (TWI0.MSTATUS & TWI_RXACK_bm))) ; //Wait until WIF set and RXACK cleared
|
57 | return 0;
|
58 | }
|
59 | else
|
60 | return 1; //Master does not own the bus
|
61 | }
|
62 | uint8_t TWI_RW(uint8_t reg, uint8_t addrW, uint8_t addrR)
|
63 | {
|
64 | TWI_start(addrW, 0);
|
65 | TWI_WRITE(reg);
|
66 | TWI_start(addrR, 1);
|
67 | uint8_t result = TWI_read(1);
|
68 | TWI_STOP();
|
69 | return (result);
|
70 | }
|
71 | void TWI_STOP(void)
|
72 | {
|
73 | TWI0.MCTRLB |= TWI_ACKACT_NACK_gc;
|
74 | TWI0.MCTRLB |= TWI_MCMD_STOP_gc;
|
75 | }
|
76 | int Mpu6050_Setup()
|
77 | {
|
78 | //START i2c
|
79 | //startI2c();//Just rate of i2c
|
80 |
|
81 | //WRITE MPU6050
|
82 | Mpu6050_writeReg (0x19, 0b00000111);//WRITE Sample Rate Divider
|
83 | Mpu6050_writeReg (0x6b, 0b00000001);//WRITE Power Management 1
|
84 | Mpu6050_writeReg (0x1b, 0b10000000);//WRITE Gyroscope Configuration (1000°/s)
|
85 | return(0);
|
86 | }
|
87 | void Mpu6050_writeReg (const uint8_t ADDRESS, const uint8_t DATA)
|
88 | {
|
89 | TWI_start(Sensor_Write, 0);
|
90 | TWI_WRITE(ADDRESS);
|
91 | TWI_WRITE(DATA);
|
92 | TWI_STOP();
|
93 | }
|
Hier ist mein "main.c" File:
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <util/delay.h>
|
4 | #include "TWI_master.h"
|
5 | #include "UART.h"
|
6 | #include "General.h"
|
7 |
|
8 | volatile uint32_t TCA_t_counter = 200; // Counter variable
|
9 | volatile uint32_t Delay1_time = 200000; // Delay1 delay value
|
10 | volatile uint32_t Delay1_old = 0; // Delay1 old counter value
|
11 |
|
12 | void timerAInit(void);
|
13 | void clkInit(void);
|
14 |
|
15 | void clkInit(void){
|
16 | CPU_CCP = 0xD8;
|
17 | CLKCTRL.MCLKCTRLA |= (1<<7); // Enables CLKOUT
|
18 | CPU_CCP = 0xD8;
|
19 | CLKCTRL.MCLKCTRLA &= ~(1<<0) & ~(1<<1); //Selects OSC20M as main clock source
|
20 | CPU_CCP = 0xD8;
|
21 | CLKCTRL.MCLKCTRLB &= ~(1<<0); //Disables main clock prescaler
|
22 | CPU_CCP = 0xD8;
|
23 | CLKCTRL.OSC20MCTRLA |= (1<<1); //Lets OSC20M run in standby
|
24 | }
|
25 | void timerAInit(void)
|
26 | {
|
27 | TCA0.SINGLE.PER = 96; // Set prescaler to 96
|
28 | TCA0.SINGLE.CTRLA |= (TCA_SINGLE_CLKSEL_DIV1_gc) | (TCA_SINGLE_ENABLE_bm); // Enable TCA0 and set CLKDIV to 8
|
29 | TCA0.SINGLE.INTCTRL |= (TCA_SINGLE_OVF_bm); // Enable interrupt
|
30 | }
|
31 | ISR(TCA0_OVF_vect)
|
32 | {
|
33 | //PORTC.OUTTGL |= (1<<0); //Test Signal
|
34 | TCA_t_counter ++; // Increases the TCA0 Counter
|
35 | TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; //Clears the TCA0 interrupt
|
36 | }
|
37 |
|
38 | int main(void)
|
39 | {
|
40 | PORTB.DIR |= (1<<0) | (1<<1) | (1<<5);
|
41 | PORTC.DIR |= (1<<0);
|
42 | TWI_init();
|
43 | clkInit();
|
44 | USART_init();
|
45 | timerAInit();
|
46 | sei(); // Enable global interrupts
|
47 | Mpu6050_Setup();
|
48 |
|
49 | while (1)
|
50 | {
|
51 | if(TCA_t_counter >= Delay1_old + Delay1_time){
|
52 | printString(" Hallo ");
|
53 | Delay1_old = TCA_t_counter;
|
54 | int rawGyroZ = TWI_RW (0x3f, Sensor_Write, Sensor_Read);
|
55 | PORTC.OUTTGL |= (1<<0); //Test Signal
|
56 | USART_write((int)rawGyroZ);
|
57 |
|
58 | // int rawAccX = readI2c (0x43);
|
59 | // int rawAccY = readI2c (0x45);
|
60 | // int rawAccZ = readI2c (0x47);
|
61 | // int rawGyroX = readI2c (0x3b);
|
62 | // int rawGyroY = readI2c (0x3d);
|
63 | // int rawGyroZ = readI2c (0x3f);
|
64 | // int rawTemperature = readI2c (0x41);
|
65 |
|
66 | }
|
67 | }
|
68 | }
|
Ich habe ertestet, dass der Chip bei der while-Schleife in der Funktion
"TWI_start" hängenbleibt. Wenn man diese auskommentiert, hängt er in der
while-Schleife in der Funktion "TWI_read" fest.
Hat jemand eine ahnung, warum der RIF nicht gesetzt wir, oder was ich
falsch mache?
Danke für die Hilfe,
Nils