use twi implementation by peterfleury and read rtc

This commit is contained in:
2019-09-21 18:41:02 +02:00
parent be90944b2f
commit 80ccc8e23c
7 changed files with 406 additions and 195 deletions

View File

@@ -1,41 +1,17 @@
#include "i2c.h"
#include "DS3231.h"
#include "pinout.h"
#include <avr/io.h>
#include "i2cmaster.h"
uint32_t DS3231_read(){
i2c_start_wait(0xD0);
i2c_write(0x00);
i2c_stop();
void DS3231_init(void){
//i2c_start(DS3231_ADDRESS);
}
int DS3231_seconds(void){
char ret = i2c_start(DS3231_ADDRESS+I2C_WRITE);
/*
USART_Transmit_String(" Return ");
//putchar(ret);
USART_Transmit_String("\n");
*/
/*
if(ret){ //failed
PORTB |= STATUS_LED_B;
i2c_stop();
}else{
// issuing start condition ok, device accessible
i2c_write(0x05); // write address = 5
i2c_write(0x75); // ret=0 -> Ok, ret=1 -> no ACK
i2c_stop();
i2c_start_wait(DS3231_ADDRESS+I2C_WRITE); // set device address and write mode
i2c_write(REG_SECONDS); // write address = 5
i2c_rep_start(DS3231_ADDRESS+I2C_READ); // set device address and read mode
ret = i2c_readNak(); // read one byte
i2c_stop();
}
return ret;
*/
i2c_start_wait(0xD1);
uint8_t sec = i2c_readAck();
uint8_t min = i2c_readAck();
uint8_t std = i2c_readNak();
i2c_stop();
return ((uint32_t)std<<16) | ((uint32_t)min<<8) | sec;
}

View File

@@ -1,94 +0,0 @@
#include "i2c.h"
#include "pinout.h"
#include <util/twi.h>
#include <avr/io.h>
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
TWSR = 1; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
}
unsigned char i2c_start(unsigned char address){
char DATA = 0b10011000;
//Send START condition
TWCR = (1<<TWINT)|
(1<<TWSTA)|
(1<<TWEN);
//Wait for TWINT Flag set. This indicates that the START condition has been transmitted.
while (!(TWCR &(1<<TWINT)));
//Check value of TWI Status Register. Mask prescaler bits. If status different from START go to ERROR.
if ((TWSR & 0xF8) != TW_START){
//ERROR();
}
//Load SLA_W into TWDR Register. Clear TWINT bit in TWCR to start transmission of address.
TWDR = address + I2C_WRITE;
TWCR = (1<<TWINT) |
(1<<TWEN);
//Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received.
while (!(TWCR & (1<<TWINT)));
//Check value of TWI Status Register. Mask prescaler bits. If status different from MT_SLA_ACK go to ERROR.
if ((TWSR & 0xF8) != TW_MT_SLA_ACK){
// ERROR();
}
//Load DATA into TWDR Register. Clear TWINT bit in TWCR to start transmission of data.
TWDR = DATA;
TWCR = (1<<TWINT) |
(1<<TWEN);
//Wait for TWINT Flag set. This indicates that the DATA has been transmitted, and ACK/NACK has been received.
while (!(TWCR &(1<<TWINT)));
//Check value of TWI Status Register. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR.
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
// ERROR();
}
//Transmit STOP condition
TWCR = (1<<TWINT)|
(1<<TWEN) |
(1<<TWSTO);
/*
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START)
return 1;
//ERROR(); //Fehlerbehandlung
TWDR = address + I2C_WRITE;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
//ERROR();
return 2;
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
return 3;
//ERROR();
TWCR = (1<<TWINT)|(1<<TWEN)|
(1<<TWSTO);
*/
return 0;
}

View File

@@ -8,7 +8,7 @@
#include "print.h"
#include "adc.h"
#include "uart.h"
#include "i2c.h"
#include "i2cmaster.h"
#include "DS3231.h"
@@ -33,44 +33,21 @@ void set_PWM_duty(int dutycycle);
int main(void){
setup();
printf("test\n\r");
while(1){
putchar('c');
_delay_ms(50);
_delay_ms(500);
check_dip_switches();
check_buttons();
char current_section[6];
for(int i = 0; i < 6; i++){
current_section[i] = text[(i+offset)%stringlength];
if(text[(i+offset)%stringlength] == ' ' && text[(i+1+offset)%stringlength] == ' '){
PORTC |= DOT;
}else{
PORTC &= ~DOT;
}
}
//for(int i = 0; i < 6; i++){}
//char test_word[6] = {'0','0','0','0','0', (char)i};
print_String(current_section);
//i2c_start(0b00101010);
// current_e
/*
for(int i = 0; i < 6; i++)
SR_Buffer[i] = i;
uint32_t clock = DS3231_read();
for(uint8_t i=0; i < 6; i++){
SR_Buffer[5-i] = number_Font[clock & 0x0F];
clock = clock >> 4;
}
print_SR_Buffer();
*/
//putchar((i2c_start(0x68))+48);
//i2c_write(0b00101010);
}
}
}
void check_dip_switches() {
@@ -198,6 +175,7 @@ void setup(){
(1 << TOIE1); //Timer Overflow Enabled
uart_init();
i2c_init();
sei(); //Enable Interrupts
//adc_setup();

202
code/src/twimaster.c Normal file
View File

@@ -0,0 +1,202 @@
/*************************************************************************
* Title: I2C master library using hardware TWI interface
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
* File: $Id: twimaster.c,v 1.4 2015/01/17 12:16:05 peter Exp $
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
* Target: any AVR device with hardware TWI
* Usage: API compatible with I2C Software Library i2cmaster.h
**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>
#include <i2cmaster.h>
/* define CPU frequency in hz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 4000000UL
#endif
/* I2C clock in Hz */
#define SCL_CLOCK 100000L
/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
TWSR = 0; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
}/* i2c_init */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed and ACK/NACK has been received
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}/* i2c_start */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
If device is busy, use ack polling to wait until device is ready
Input: address and transfer direction of I2C device
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
/* device busy, send stop condition to terminate write operation */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}
}/* i2c_start_wait */
/*************************************************************************
Issues a repeated start condition and sends address and transfer direction
Input: address and transfer direction of I2C device
Return: 0 device accessible
1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}/* i2c_rep_start */
/*************************************************************************
Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
/* send stop condition */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
}/* i2c_stop */
/*************************************************************************
Send one byte to I2C device
Input: byte to be transfered
Return: 0 write successful
1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// send data to the previously addressed device
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits
twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;
}/* i2c_write */
/*************************************************************************
Read one byte from the I2C device, request more data from device
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readAck */
/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readNak */