Biblioteca I2C para FRDM-KL25Z

Olá caro leitor, neste quarto artigo da série Biblioteca de software para a FRDM-KL25Z. Será apresentada a biblioteca de software para o barramento de comunicação I²C (Inter-Integrated Circuit) e exemplo de aplicação utilizando o módulo Tiny RTC I2C.

 

As bibliotecas aqui apresentadas são compatíveis com o Kinetis Design Studio IDE e CodeWarrior IDE. Também são facilmente portáveis para as demais Freedom Board.

 

O microcontrolador presente na Freedom Board KL25Z, o MKL25Z128VLK4, contém dois módulos de comunicação I²C (I2C0 e I2C1), que trabalham com dados de 8 bits. Os módulos permitem trabalhar tanto no modo mestre (Master) ou no modo escravo (Slave). O módulo de comunicação I²C deste microcontrolador possui também interface DMA (Direct Memory Access).

 

A seguir serão apresentadas as configurações mínimas para trabalhar com o I²C na Freedom Board KL25Z no modo mestre. Apresentando funções de inicialização do periférico e funções de escrita e leitura, e por fim, um exemplo de aplicação de utilização da comunicação I²C.

 

 

Introdução I²C

 

O I²C, IIC ou I2C (Inter-Integrated Circuit - Circuito Inter-integrado) é barramento de comunicação serial síncrono Mestre/Escravo, desenvolvido pela empresa  Philips Semiconductor (hoje NXP Semiconductors). Algumas empresas utilizam outra nomenclatura: TWI (Two Wire Interface - Interface de Dois Fios) ou 2-Wire Serial, TWSI (Two-Wire Serial Interface - Interface Serial de Dois Fios).

 

A comunicação I²C possui duas linhas de sinais SDA (Serial Data) e SCL (Serial Clock Line), sendo um sinal para transmissão de dados e outro o sinal de Clock. O SDA é um sinal bidirecional, permitindo a troca de dados entre o mestre e os escravo de maneira não simultânea (Half-Duples). O SCL é sinal de Clock paro sincronismo da comunicação, este sinal é gerado pelo mestre.

 

 

Outra característica muito importante a ser mencionada sobre a comunicação I2C é o fato que suas duas linhas de sinais utiliza Dreno Aberto (Coletor Aberto), significa que o transistor é para chavear o sinal para 0 (0 Volts - GND). Para chavear o sinal para 1 (3,3 ou 5 Volts - VCC) se faz necessário utilizar resistores  de pull-up em suas linhas. Tipicamente são utilizados resistores com valores entre 2K2 a 4K7 Ohms.

 

A comunicação I²C pode endereçar até 127 dispositivos, porque faz o uso de 7 Bits de endereçamento (existem alguns dispositivos com endereçamento de 10 Bits, permitindo o endereçamento de até 1023 dispositivos). Para mais informações a respeito da comunicação I²C, recomendo a série de artigos escrita pelo o Francesco SaccoMódulo Tiny RTC I2C”, onde é explicado com maior detalhes.

 

 

 

Inicializando I²C

 

Configuração da fonte de Clock

O primeiro item a ser configurado para o funcionamento da comunicação I²C é a fonte de Clock. Para realizar esta tarefa deve utilizar o registrador System Clock Gating Control Register 4 (SIM_SCGC4).

 

Para escrever no registrador deve utilizar as macros SIM_SCGC4_I2C0_MASK para o I2C0 e SIM_SCGC4_I2C1_MASK  para I2C1.

 

As figuras abaixo ilustram os parâmetros do registrador.

 

I2C para FRDM-KL25Z

 

 

Configuração dos pinos do barramento de comunicação I²C

O segundo item a ser configurado é os pinos para a comunicação I²C. Cada periférico de comunicação I²C possui quatro alternativas de pinos. A seguir é apresentada a tabelas com os pinos.

 

I2C0

Pinos I²C

Alternativa 0

Alternativa 1

Alternativa 2

Alternativa 3

SCL

PTE24

PTB0

PTB2

PTC8

SDA

PTE25

PTB1

PTB3

PTC9

I2C1

Pinos I²C

Alternativa 0

Alternativa 1

Alternativa 2

Alternativa 3

SCL

PTE0

PTA3

PTC1

PTC10

SDA

PTE1

PTA4

PTC2

PTC11

 

Para definir as funcionalidades dos pinos devemos seguir as instruções do Signal Multiplexing and Pin Assignments (Multiplexador de sinais do pino). Para realizar essa tarefa deve-se utilizar a macro PORT_PCR_MUX(x) para configurar o multiplexador de sinais do pino, onde x é alternativa de funcionalidade do pino. A seguir são apresentas imagens com a tabela com KL25 Signal Multiplexing and Pin Assignments.

 

 

 

 

 

 

Configuração dos Parâmetros

O primeiro parâmetro que deve ser configurado é a frequência do Clock (Baud Rate). Para realizar essa operação deve-se utilizar o registrador I2C Frequency Divider register (I2Cx_F). Os dois Bits mais significativos do registrador é MULT. Os Bits MULT definem o fator de multiplicação, que é utilizado para definir a taxa de transmissão da comunicação I²C.

 

Para configurar os Bits MULT deve-se utilizar a macro I2C_F_MULT(x), onde x é valor do fator.

 

Os demais Bits são os INC, são os Bits que compõem o valor do Prescales. Em conjunto com o MULT definem o valor da taxa de transmissão. A macro I2C_F_ICR(x) é utilizada para configurar o INC, x é valor do Prescale. As figuras abaixo ilustram os detalhes do registrador.

 

 

 

 

O último item que devemos configurar é o registrador I2C Control Register 1 (I2Cx_C1). É neste registrador onde se encontra os principais itens para controlar a comunicação I²C. A seguir é apresentada tabela com cada Bit do registrador, sua macro correspondente e descrição do mesmo. 

 

Bit

Macro

Descrição

IICEN

I2C_C1_IICEN_MASK

Habilita I²C

IICIE

I2C_C1_IICIE_MASK

Habilita Interrupção

MST

I2C_C1_MST_MASK

Seleção do Modo Mestre

TX

I2C_C1_TX_MASK

Seleção do Modo de Transmissão

TXAK

I2C_C1_TXAK_MASK

Transmite o Acknowledge Enable

RSTA

I2C_C1_RSTA_MASK

Repetir START

WUEN

I2C_C1_WUEN_MASK

Habilita Wakeup

DMAEN

I2C_C1_DMAEN_MASK

Habilita DMA

 

A seguir são apresentadas imagens que ilustram com detalhe cada Bit do registrador I2C Control Register 1 (I2Cx_C1).

 

 

 

  

 

Leitura e Escrita da Comunicação I²C

 

Para realizar leitura e escrita no barramento de comunicação I²C será necessário apresentar mais dois registradores.

 

O primeiro registrador é I2C Status register (I2Cx_S), possui Bits de leitura e escrita, utilizada para gerenciar a comunicação I²C. A seguir temos algumas imagens para demonstrar os Bits do registrador.

 

 

 

 

O segundo registrador a ser apresentado é o I2C Data I/O register (I2Cx_D). É através desse registrador que são feitas as leituras e escritas no barramento de comunicação I²C. As figuras a seguir ilustram com detalhes o registrador.

 

 

 

A seguir é apresentada a biblioteca desenvolvida para o barramento de comunicação I²C para utilizar com a Freedom Board KL25Z.

 

O código fonte abaixo é do arquivo i2c.h.

 

/*
 * i2c.h
 *
 *  Created on: 14/04/2017
 *      Author: evandro
 */

#ifndef SOURCES_I2C_H_
#define SOURCES_I2C_H_

#include "MKL25Z4.h"
#include "stdbool.h"

#define ALT0		0
#define ALT1		1
#define ALT2		2
#define ALT3		3
#define MULT0		0
#define MULT1		1
#define MULT2		2
#define I2C_WRITE	0	// Master write
#define I2C_READ	1	// Master read

bool i2c_Init(I2C_MemMapPtr i2c, uint8_t alt, uint8_t mult, uint8_t icr);
void i2c_DisableAck(I2C_MemMapPtr i2c);
void i2c_EnableAck(I2C_MemMapPtr i2c);
void i2c_RepeatedStart(I2C_MemMapPtr i2c);
void i2c_EnterRxMode(I2C_MemMapPtr i2c);
void i2c_Start(I2C_MemMapPtr i2c);
void i2c_Stop(I2C_MemMapPtr i2c);
void i2c_Wait(I2C_MemMapPtr i2c);
void i2c_WriteByte(I2C_MemMapPtr i2c,uint8_t data);

void i2c_WriteRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
uint8_t RegisterAddress, uint8_t data);

uint8_t i2c_ReadByte(I2C_MemMapPtr i2c);

uint8_t i2c_ReadRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,uint8_t RegisterAddress);

uint8_t i2c_ReadMultRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
uint8_t RegisterAddress,uint8_t n_data, uint8_t *res);

void i2c_WriteMultRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
uint8_t RegisterAddress, uint8_t n_data, uint8_t *data);

void delay(uint32_t t);

#endif /* SOURCES_I2C_H_ */

 

A seguir temos o código fonte do arquivo i2c.c.

 

/*
 * i2c.c
 *
 *  Created on: 14/04/2017
 *      Author: evandro
 */
#include "i2c.h"

/****************************************************************************************
*
*****************************************************************************************/
bool i2c_Init(I2C_MemMapPtr i2c, uint8_t alt, uint8_t mult, uint8_t icr)
{
	if(i2c == I2C0)
	{
		switch(alt)
		{
			case ALT0:
				SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;      //Turn on clock to E module
				PORTE_PCR24 = PORT_PCR_MUX(0x5);    	//Set PTE24 to mux 5 [I2C_SCL]
				PORTE_PCR25 = PORT_PCR_MUX(0x5);    	//Set PTE25 to mux 5 [I2C_SDA]
			break;

			case ALT1:
				SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;      //Turn on clock to E module
				PORTB_PCR0 = PORT_PCR_MUX(0x2);    		//Set PTB0 to mux 2 [I2C_SCL]
				PORTB_PCR1 = PORT_PCR_MUX(0x2);    		//Set PTB1 to mux 2 [I2C_SDA]
			break;

			case ALT2:
				SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;      //Turn on clock to E module
				PORTB_PCR2 = PORT_PCR_MUX(0x2);    		//Set PTB2 to mux 2 [I2C_SCL]
				PORTB_PCR3 = PORT_PCR_MUX(0x2);    		//Set PTB3 to mux 2 [I2C_SDA]
			break;

			case ALT3:
				SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;      //Turn on clock to E module
				PORTC_PCR8 = PORT_PCR_MUX(0x2);    		//Set PTB2 to mux 2 [I2C_SCL]
				PORTC_PCR9 = PORT_PCR_MUX(0x2);    		//Set PTB3 to mux 2 [I2C_SDA]
			break;

			default:
				return false;
			break;
		}
		SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK;
	}
	else if (i2c == I2C1)
	{
		switch(alt)
		{
			case ALT0:
				SIM_SCGC5 |= SIM_SCGC5_PORTE_MASK;      //Turn on clock to E module
				PORTE_PCR0 = PORT_PCR_MUX(0x6);    		//Set PTE0 to mux 6 [I2C_SDA]
				PORTE_PCR1 = PORT_PCR_MUX(0x6);    		//Set PTE1 to mux 6 [I2C_SCL]
			break;

			case ALT1:
				SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;      //Turn on clock to A module
				PORTA_PCR3 = PORT_PCR_MUX(0x2);    		//Set PTA3 to mux 2 [I2C_SCL]
				PORTA_PCR4 = PORT_PCR_MUX(0x2);    		//Set PTA4 to mux 2 [I2C_SDA]
			break;

			case ALT2:
				SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;      //Turn on clock to C module
				PORTC_PCR1 = PORT_PCR_MUX(0x2);    		//Set PTC1 to mux 2 [I2C_SCL]
				PORTC_PCR2 = PORT_PCR_MUX(0x2);    		//Set PTC2 to mux 2 [I2C_SDA]
			break;

			case ALT3:
				SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;      //Turn on clock to E module
				PORTC_PCR10 = PORT_PCR_MUX(0x2);    	//Set PTC10 to mux 2 [I2C_SCL]
				PORTC_PCR11 = PORT_PCR_MUX(0x2);    	//Set PTC11 to mux 2 [I2C_SDA]
			break;

			default:
				return false;
			break;
		}
		SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;
	}
	else
	{
		return false;
	}
	i2c->F = I2C_F_ICR(icr) | I2C_F_MULT(mult);
	i2c->C1 = I2C_C1_IICEN_MASK; // I2C Enable
	return true;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_DisableAck(I2C_MemMapPtr i2c)
{
	i2c->C1 |= I2C_C1_TXAK_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_EnableAck(I2C_MemMapPtr i2c)
{
	i2c->C1 &= ~I2C_C1_TXAK_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_RepeatedStart(I2C_MemMapPtr i2c)
{
	i2c->C1 |= I2C_C1_RSTA_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_EnterRxMode(I2C_MemMapPtr i2c)
{
	i2c->C1 &= ~I2C_C1_TX_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_Start(I2C_MemMapPtr i2c)
{
	i2c->C1 |= I2C_C1_TX_MASK;
	i2c->C1 |= I2C_C1_MST_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_Stop(I2C_MemMapPtr i2c)
{
	i2c->C1 &= ~I2C_C1_MST_MASK;
	i2c->C1 &= ~I2C_C1_TX_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_Wait(I2C_MemMapPtr i2c)
{
	uint32_t i = 0;
	i = 1000000;

	while(((i2c->S & I2C_S_IICIF_MASK) == 0) && i)
	{
		i--;
	}
	i2c->S |= I2C_S_IICIF_MASK;
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_WriteByte(I2C_MemMapPtr i2c,uint8_t data)
{
	i2c->D = (uint8_t)data;
}
/****************************************************************************************
*
*****************************************************************************************/
uint8_t i2c_ReadByte(I2C_MemMapPtr i2c)
{
	return (uint8_t)( i2c->D );
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_WriteRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
                       uint8_t RegisterAddress, uint8_t data)
{
	i2c_Start(i2c);
	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_WRITE));
	i2c_Wait(i2c);

	i2c_WriteByte(i2c,RegisterAddress);
	i2c_Wait(i2c);

	i2c_WriteByte(i2c,data);
	i2c_Wait(i2c);

	i2c_Stop(i2c);

	delay(50);
}
/****************************************************************************************
*
*****************************************************************************************/
uint8_t i2c_ReadRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,uint8_t RegisterAddress)
{
	uint8_t res = 0;

	i2c_Start(i2c);
	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_WRITE));
	i2c_Wait(i2c);

	i2c_WriteByte(i2c,RegisterAddress);
	i2c_Wait(i2c);

	i2c_RepeatedStart(i2c);

	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_READ));
	i2c_Wait(i2c);

	i2c_EnterRxMode(i2c);
	i2c_DisableAck(i2c);

	res = i2c_ReadByte(i2c);
	i2c_Wait(i2c);
	i2c_Stop(i2c);
	res = i2c_ReadByte(i2c);
	delay(50);

	return res;
}
/****************************************************************************************
*
*****************************************************************************************/
uint8_t i2c_ReadMultRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
                             uint8_t RegisterAddress,uint8_t n_data, uint8_t *res)
{
	uint8_t i = 0;

	i2c_Start(i2c);
	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_WRITE));
	i2c_Wait(i2c);

	i2c_WriteByte(i2c,RegisterAddress);
	i2c_Wait(i2c);

	i2c_RepeatedStart(i2c);

	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_READ));
	i2c_Wait(i2c);

	i2c_EnterRxMode(i2c);
	i2c_EnableAck(i2c);

	i = i2c_ReadByte(i2c);
	i2c_Wait(i2c);

	for(i=0;i<(n_data-2);i++)
	{
		*res = i2c_ReadByte(i2c);
		res++;
		i2c_Wait(i2c);
	}

	i2c_DisableAck(i2c);

	*res = i2c_ReadByte(i2c);
	res++;
	i2c_Wait(i2c);

	i2c_Stop(i2c);

	*res = i2c_ReadByte(i2c);

	delay(50);
}
/****************************************************************************************
*
*****************************************************************************************/
void i2c_WriteMultRegister(I2C_MemMapPtr i2c,uint8_t SlaveAddress,
                           uint8_t RegisterAddress, uint8_t n_data, uint8_t *data)
{
	uint8_t i = 0;

	i2c_Start(i2c);
	i2c_WriteByte(i2c, ((SlaveAddress << 1) | I2C_WRITE));
	i2c_Wait(i2c);

	i2c_WriteByte(i2c,RegisterAddress);
	i2c_Wait(i2c);

	for(i=0;i<n_data;i++)
	{
		i2c_WriteByte(i2c,*data);
		i2c_Wait(i2c);
		data++;
	}
	i2c_Stop(i2c);

	delay(50);
}
/****************************************************************************************
*
*****************************************************************************************/
void delay(uint32_t t)
{
	uint32_t cnt = 0;
	for(cnt=0; cnt<t; cnt++)
	{
		__asm("nop");
	};
}
/*****************************************************************************************/

 

 

Aplicação com o Módulo Tiny RTC I2C

 

O módulo Tiny RTC I2C é composto pelo RTC (Real-Time Clock) DS1307 com bateria e memória EEPROM AT24C32. Para mais detalhes sobre o módulo Tiny RTC I2C recomendo que veja a série de artigos produzida pelo Francesco SaccoMódulo Tiny RTC I2C”.

 

Na figura a seguir temos o circuito elétrico que foi montado para aplicação.

 

 

Abaixo temos o código fonte ds1307.h.

 

/*
 * ds1307.h
 *
 *  Created on: 14/04/2017
 *      Author: evandro
 */

#ifndef SOURCES_DS1307_H_
#define SOURCES_DS1307_H_

#include "MKL25Z4.h"
#include "i2c.h"
#include "stdbool.h"

#define END_DS1307 0b01101000//0x68

typedef struct {
	uint8_t seconds;
	uint8_t minutes;
	uint8_t hours;
	uint8_t day;
	uint8_t date;
	uint8_t month;
	uint8_t year;
}data_ds1307;

void Init_DS1307(void);
bool Read_DS1307(data_ds1307 *dt);
bool Write_DS1307(data_ds1307 dt);
//uint8_t Read_DS1307_Byte(uint8_t end);

#endif /* SOURCES_DS1307_H_ */

 

Abaixo é apresentado o código fonte ds1307.c.

 

/*
 * ds1307.c
 *
 *  Created on: 14/04/2017
 *      Author: evandro
 */
#include "ds1307.h"

void Init_DS1307(void)
{
	i2c_Init(I2C1,ALT0,MULT0,0x14);
}
/****************************************************************************************
*
*****************************************************************************************/
bool Read_DS1307(data_ds1307 *dt)
{
	uint8_t data[8];
	uint8_t i = 0;
	uint8_t dado0;
	uint8_t dado1;
	uint8_t dado2;

	i2c_ReadMultRegister(I2C1,END_DS1307,0x00,7,&data);

	dado0 = (uint8_t)(data[0] & 0b00001111);
	dado1 = (uint8_t)(data[0] & 0b01110000);
	dado1 = (uint8_t)(dado1 >> 4);
	dt->seconds = (uint8_t)((dado1*10)+dado0);

	dado0 = (uint8_t)(data[1] & 0b00001111);
	dado1 = (uint8_t)(data[1] & 0b01110000);
	dado1 = (uint8_t)(dado1 >> 4);
	dt->minutes = (uint8_t)((dado1*10)+dado0);

	if((data[2] & 0b01000000) == 0)
	{
		// Modo 24 Horas
		dado0 = (uint8_t)(data[2] & 0b00001111);
		dado1 = (uint8_t)(data[2] & 0b00010000);
		dado1 = (uint8_t)(dado1 >> 4);
		dado2 = (uint8_t)(data[2] & 0b00100000);
		dado2 = (uint8_t)(dado2 >> 5);
		dt->hours = (uint8_t)( (dado2*20) + (dado1*10) + dado0 );
	}
	else
	{
		// Modo 12 Horas
		dado0 = (uint8_t)(data[2] & 0b00001111);
		dado1 = (uint8_t)(data[2] & 0b00010000);
		dado1 = (uint8_t)(dado1 >> 4);
		dado2 = (uint8_t)(data[2] & 0b00100000);
		dado2 = (uint8_t)(dado2 >> 5);
		dt->hours = (uint8_t)((dado1*10) + dado0);
	}

	dt->day = (uint8_t)(data[3]);

	dado0 = (uint8_t)(data[4] & 0b00001111);
	dado1 = (uint8_t)(data[4] & 0b00110000);
	dado1 = (uint8_t)(dado1 >> 4);
	dt->date = (uint8_t)((dado1*10)+dado0);

	dado0 = (uint8_t)(data[5] & 0b00001111);
	dado1 = (uint8_t)(data[5] & 0b00010000);
	dado1 = (uint8_t)(dado1 >> 4);
	dt->month = (uint8_t)((dado1*10)+dado0);

	dado0 = (uint8_t)(data[6] & 0b00001111);
	dado1 = (uint8_t)(data[6] & 0b11110000);
	dado1 = (uint8_t)(dado1 >> 4);
	dt->year = (uint8_t)((dado1*10)+dado0);
}
/****************************************************************************************
*
*****************************************************************************************/
bool Write_DS1307(data_ds1307 dt)
{
	uint8_t data[8];
	uint8_t aux = 0;

	// minutos
	if(dt.minutes < 60)
	{
		//dado0  = (uint8_t)((dt.minutes / 10) << 4);
		//dado0 += (uint8_t)(dt.minutes % 10);
		data[0]  = (uint8_t)((dt.minutes / 10) << 4);
		data[0] += (uint8_t)(dt.minutes % 10);
	}
	else
	{
		return false;
	}
	// horas
	if(dt.hours <= 9)
	{
		//dado1 = dt.hours;
		data[1] = dt.hours;
		//teste = 0b00000001;
	}
	else if((dt.hours > 9)&&(dt.hours < 19))
	{
		aux     = (uint8_t)(dt.hours % 10);
		data[1] = (uint8_t)(0b00010000 + aux);
		//teste |= 0b00000010;
	}
	else if((dt.hours > 19)&&(dt.hours < 23))
	{
		aux     = (uint8_t)(dt.hours % 10);
		data[1] = (uint8_t)(0b00100000 + aux);
		//teste |= 0b00000010;
	}
	else
	{
		return false;
	}

	//  dia da semana
	if((dt.day >= 1)&&(dt.day <= 7))
	{
		//dado2 = (uint8_t)(dt.day);
		data[2] = (uint8_t)(dt.day);
	}
	else
	{
		return false;
	}
	// mes
	if((dt.month >= 1)&&(dt.month <= 12))
	{
		//dado4  = (uint8_t)((dt.mount / 10) << 4);
		//dado4 += (uint8_t)(dt.mount % 10);
		data[4]  = (uint8_t)((dt.month / 10) << 4);
		data[4] += (uint8_t)(dt.month % 10);
 	}
	else
	{
		return false;
	}
	//dia do mes
	if((dt.date>=1)&&(dt.date<=31))
	{
		//dado3  = (uint8_t)((dt.date / 10) << 4);
		//dado3 += (uint8_t)(dt.date % 10);
		data[3]  = (uint8_t)((dt.date / 10) << 4);
		data[3] += (uint8_t)(dt.date % 10);
	}
	else
	{
		return false;
	}
	// ano
	if(dt.year < 100)
	{
		//dado5  = (uint8_t)((dt.year / 10) << 4);
		//dado5 += (uint8_t)(dt.year % 10);
		data[5]  = (uint8_t)((dt.year / 10) << 4);
		data[5] += (uint8_t)(dt.year % 10);
	}
	else
	{
		return false;
	}

	i2c_WriteMultRegister(I2C1,END_DS1307,0x01,6,&data);

	return true;
}
/****************************************************************************************
*
*****************************************************************************************/

 

A seguir é demonstrado o código fonte main.c da aplicação.

 

/*
*
*/
#include "MKL25Z4.h"
#include "i2c.h"
#include "gpio.h"
#include "ds1307.h"

data_ds1307 rtc, rtc_in;
uint32_t i = 0;

int main(void)
{
        // Inicializa barramento I2C - DS1307
	Init_DS1307();

        // prepara o dados para ser salvos no RTC DS1307
        // 02:17 - 7 (sabado) - 15/04/17
	rtc_in.minutes = 17; // minutos 
	rtc_in.hours = 2;    // horas
	rtc_in.day = 7;      // dia da semana
	rtc_in.date = 15;    // dia do mes
	rtc_in.month = 4;    // mes
	rtc_in.year = 17;    // ano

	Write_DS1307(rtc_in); // Configura o RTC DS1307

	while(1)
    	{		
  		for(i=0;i<500000;i++); // delay

  		Read_DS1307(&rtc); // Le dados do RTC DS1307

  		rtc.date;
  		rtc.day;
  		rtc.hours;
  		rtc.minutes;
  		rtc.month;
  		rtc.seconds;
  		rtc.year;
  		//i = 0;
	}
}

 

 

Conclusão

 

Neste artigo foi apresentada mais uma biblioteca de software para a Freedom Board KL25Z e também a biblioteca a realizar leitura e escrita no RTC DS1307.

 

Nos próximos artigos vamos apresentar outras bibliotecas de software (Timer, UART e entre outras) para utilizar com FRDM-KL25. A biblioteca apresentada aqui está disponível no meu GitHub.

 

 

Referências

 

KL25 Sub-Family Reference Manual 

Github 

DS1307 

I2C Bus Specification 

Módulo Tiny RTC I2C 

I²C

Outros artigos da série

<< Biblioteca SPI para a placa FRDM-KL25ZBiblioteca PWM para FRDM-KL25Z >>
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Evandro Teixeira
Desenvolvedor de Sistemas Embarcados. Sou formado Técnico em Instrumentação e Automação Industrial/Mecatrônica pelo Colégio Salesiano Dom Bosco de Americana-SP, cursei o Engenharia Elétrica com Ênfase em Eletrônica pela UNISAL Centro Universitário Salesiano de São Paulo e atualmente estou cursando Superior de Tecnologia em Análise e Desenvolvimento de Sistemas pela UNIP Universidade Paulista.

Deixe um comentário

avatar
 
  Notificações  
Notificar