STM32 and MLX90614 non-contact temperature sensor. I2C connection

The MLX90614 sensor is a non-contact sensor that reads the temperature of an object by receiving and converting infrared radiation. It can work in three modes: thermostat, PWM output and SMBus. In thermostat mode, the sensor does not need a controller, it just keeps the temperature within the specified limits by controlling the open drain load driver. In PWM mode, a PWM signal appears at the sensor output, the duty cycle of which depends on the temperature. In order to connect to the controller, the most interesting mode is SMBus. Since this protocol is electrically and signalally compatible with I2C, we will work with the sensor using hardware I2C. He will be discussed in this article. All sensor modes are configured by writing to specific EEPROM cells. By default, the sensor is in SMBus mode.


Appearance and connection diagram

. " " STM32F103C8T6 , . 2 I2C. . PB6 - SCL, PB7 - SDA. , 4.7 .

, : mlx90614.h mlx90614.c . LCD A2004 . .

.

#ifndef I2C_DEVICES_I2C_H_
#define I2C_DEVICES_I2C_H_

#include "stm32f1xx.h"
#include <stdio.h>
#include "delay.h"

#define F_APB1 36 													//   APB1
#define TPCLK1 ( 1000/F_APB1 ) 							//   APB1 ns. ~ 28
#define CCR_VALUE ( 10000 /(TPCLK1 * 2 ) ) 	//   CCR  36  ~ 179
#define TRISE_VALUE ( 1000 / TPCLK1)

. stm32f1xx.h. stdio.h , char LCD. delay.h - .

I2C. . , F_APB1, .

, : RAM EEPROM. RAM . , RAM . " ". . , . MLX90614 . , . EEPROM . .

//---------------- RAM addresses --------------------------------------------
#define MLX90614_RAW_IR_1 0x04		//    
#define MLX90614_RAW_IR_2 0x05
#define MLX90614_TA 0x06					//   
#define MLX90614_TOBJ_1 0x07			//     
#define MLX90614_TOBJ_2 0x08			//     

//--------------- EEPROM addresses ------------------------------------------
#define MLX90614_TO_MAX 0x00
#define MLX90614_TO_MIN 0x01
#define MLX90614_PWM_CTRL 0x02
#define MLX90614_TA_RANGE 0x03
#define MLX90614_EMISSIVITY 0x04
#define MLX90614_CONFIG_REGISTER_1 0x05
#define MLX90614_SMBUS_ADDRESS 0x0E // LSByte only
#define MLX90614_ID_NUMBER_1 0x1C
#define MLX90614_ID_NUMBER_2 0x1D
#define MLX90614_ID_NUMBER_3 0x1E
#define MLX90614_ID_NUMBER_4 0x1F

, .

//--------------- Commands ------------------------------------------------
#define MLX90614_RAM_ACCESS 0 					//   RAM
#define MLX90614_EEPROM_ACCESS 0x20 		//   EEPROM
#define MLX90614_READ_FLAGS 0xF0 				//  
#define MLX90614_ENTER_SLEEP_MODE 0xFF 	//  
#define MLX90614_READ 1									//    
#define MLX90614_WRITE 0								//    

. , . , I2C , - 5A. , , . .

:

void mlx90614Init( void );
double getTemp_Mlx90614_Double( uint16_t address, uint8_t ram_address );
void getTemp_Mlx90614_CharArray( uint16_t address, uint8_t ram_address, char* buf );

uint16_t getAddrFromEEPROM( uint16_t address );
int setAddrToEEPROM ( uint16_t address, uint16_t new_address );

uint16_t readEEPROM( uint16_t address, uint16_t eeprom_address );
void writeEEPROM ( uint16_t address, uint16_t eeprom_address, uint16_t data );

#endif /* I2C_DEVICES_I2C_H_ */

void mlx90614Init( void )

I2C

double getTempMlx90614Double( uint16t address, uint8t ram_address )

double . , . RAM . RAM , 1 2.

void getTempMlx90614CharArray( uint16t address, uint8t ram_address, char* buf )

, , char , . LCD

uint16t getAddrFromEEPROM( uint16t address )

, EEPROM. .

int setAddrToEEPROM ( uint16t address, uint16t new_address )

EEPROM. .

uint16t readEEPROM( uint16t address, uint16t eepromaddress )

EEPROM

void writeEEPROM ( uint16t address, uint16t eepromaddress, uint16t data )

EEPROM

. .

void mlx90614Init(void){

	 delay_ms(120);																//        

RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;							//  
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;							//  i2c1

GPIOB->CRL |= GPIO_CRL_MODE6 | GPIO_CRL_MODE7;	//  50 
GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7; 		//  -  

I2C1->CR2 &= ~I2C_CR2_FREQ; 										//       APB1
I2C1->CR2 |= F_APB1; 														//    APB1    I2C 
I2C1->CR1 &= ~I2C_CR1_PE; 											//   I2C    CCR
I2C1->CCR &= ~I2C_CCR_CCR;
I2C1->CCR |=  CCR_VALUE;
I2C1->TRISE |=  TRISE_VALUE;

I2C1->CR1 |= I2C_CR1_ENPEC; 										//   PEC
I2C1->CR1 |= I2C_CR1_PE;												//   I2C
I2C1->CR1 |= I2C_CR1_ACK; 											//  ACK

}

. F_APB1, CCR_VALUE TRISE_VALUE , . I2C CCR ( ) ACK I2C , ACK .

double getTemp_Mlx90614_Double( uint16_t address,
								uint8_t ram_address){

	 uint16_t	temp ; 																// 
	 uint8_t	temp_lsb ;														//   
	 double temp_result ; 													//   
	 double temp_double ;														// ,    double

	 address = address<<1; 													//     (  
	 	 	 	 	 	 	 	 	 	 	 														//   1-  /)
	 I2C1->CR1 |= I2C_CR1_START;
	 while (!(I2C1->SR1 & I2C_SR1_SB)){}

	 (void) I2C1->SR1;

	 I2C1->DR = address | MLX90614_WRITE; 					//   ,   MLX90614
	 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

	 (void) I2C1->SR1;
	 (void) I2C1->SR2;

	 I2C1->DR= ram_address;													//   RAM   MLX90614
	 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

	 I2C1->CR1 |= I2C_CR1_START;										//  
	 while (!(I2C1->SR1 & I2C_SR1_SB)){}

	 (void) I2C1->SR1;

	 I2C1->DR = address | MLX90614_READ;						//     
	 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

	 (void) I2C1->SR1;
	 (void) I2C1->SR2;

	 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

	 temp_lsb = I2C1->DR;														//   

	 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

	 temp = I2C1->DR;																//   

	 I2C1->CR1 |= I2C_CR1_STOP;

	 temp = (temp & 0x007F) << 8;										//   ,    
	 temp |= temp_lsb;
	 temp_double = (double) temp; 									//    double
	 temp_result =  ((temp_double * 0.02)- 0.01 );	//    
	 temp_result = temp_result - 273.15; 						//    . 



return temp_result;


 }

, 1 , 1 , 0 - . I2C. 5A, B4 B5 . , , . . . , - (temp & 0x007F).

, LCD, . void getTempMlx90614CharArray, char , sprintf(), stdio.h

void getTemp_Mlx90614_CharArray( uint16_t address, uint8_t ram_address, char* buf){

	double t;
	t = getTemp_Mlx90614_Double(address,ram_address);

	 sprintf(buf, "%.1f",t);

	return ;

}

RAM :

  1. START

  2. , 1 (). - 0

  3. RAM RAM. RAM .

  4. START

  5. 1 .

  6. STOP

. , . EEPROM .

EEPROM :

  1. START

  2. , 1 (). - 0

  3. EEPROM EEPROM ( )

  4. START

  5. STOP

EEPROM

uint16_t readEEPROM( uint16_t address, uint16_t eeprom_address ){

	 uint16_t	data_msb;
	 uint16_t	data_lsb;
	 uint16_t data_result;

	 address = address<<1; 																//     (    + 1  /)

	 	 I2C1->CR1 |= I2C_CR1_START;
		 while (!(I2C1->SR1 & I2C_SR1_SB)){}

		 (void) I2C1->SR1;

		 I2C1->DR = address | MLX90614_WRITE; 							//   ,   MLX90614
		 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

		 (void) I2C1->SR1;
		 (void) I2C1->SR2;

		 I2C1->DR= eeprom_address | MLX90614_EEPROM_ACCESS;	//   EEPROM  MLX90614
		 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

		 I2C1->CR1 |= I2C_CR1_START;												//  
		 while (!(I2C1->SR1 & I2C_SR1_SB)){}

		 (void) I2C1->SR1;

		 I2C1->DR = address | MLX90614_READ;								//     
		 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

		 (void) I2C1->SR1;
		 (void) I2C1->SR2;

		 //I2C1->CR1 &= ~I2C_CR1_ACK;
		 while (!(I2C1->SR1 & I2C_SR1_RXNE)){};

		 data_lsb = I2C1->DR;															//   

		 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

		 data_msb = I2C1->DR;															//   


		 I2C1->CR1 |= I2C_CR1_STOP;


		data_result = ((data_msb << 8) | data_lsb) ;

		 return data_result;


}

EEPROM RAM. .

. :

  1. START

  2. ,

  3. EEPROM EEPROM

  4. PEC ( )

  5. STOP

, . , , .

EEPROM

void writeEEPROM ( uint16_t address, uint16_t eeprom_address, uint16_t data ){


		 address = address<<1; 																//     (..    + 1  /)

		 	 I2C1->CR1 |= I2C_CR1_START;
			 while (!(I2C1->SR1 & I2C_SR1_SB)){}

			 (void) I2C1->SR1;

			 I2C1->DR = address | MLX90614_WRITE; 							//   ,   MLX90614
			 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

			 (void) I2C1->SR1;
			 (void) I2C1->SR2;

			 I2C1->DR= eeprom_address | MLX90614_EEPROM_ACCESS;	//   EEPROM  MLX90614
			 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

			 I2C1->DR =  ( uint8_t ) ( data & 0x00FF );					//   

			 while(!(I2C1->SR1 & I2C_SR1_BTF)){}

			 I2C1->DR = ( uint8_t ) ( data >> 8 )	;							//   
			 while(!(I2C1->SR1 & I2C_SR1_BTF)){}

			 I2C1->CR1 |= I2C_CR1_PEC;													//  PEC
			 I2C1->CR1 |= I2C_CR1_STOP;


			 return ;
}

EEPROM. . , .

uint16_t getAddrFromEEPROM ( uint16_t address ){

	uint16_t addr_eeprom;
	addr_eeprom = readEEPROM( address, MLX90614_SMBUS_ADDRESS );

	return addr_eeprom;

}

. , readEEPROM() EEPROM .

EEPROM . MLX90614 EEPROM:

  1. ,

  2. 10

  3. 10

  4. , ,

. . , , , . - , EEPROM ? ? , . , .

EEPROM

int setAddrToEEPROM ( uint16_t address, uint16_t new_address ){

	uint16_t addr;

	writeEEPROM ( address, MLX90614_SMBUS_ADDRESS, 0x0); 					//  
	delay_ms(10);
	writeEEPROM (address, MLX90614_SMBUS_ADDRESS, new_address ); 	//   
	delay_ms(10);
	addr = readEEPROM ( address, MLX90614_SMBUS_ADDRESS );			 	//   

	if ( addr == new_address){
		return 1;
	}

	else return 0;

}

. main()

#include "main.h"
#include <stdio.h>
int main (void){

	clk_ini(); 										//   
	lcd_2004a_init(); 						//   a2004
	mlx90614Init(); 							//  I2C  

	uint16_t geted_eeprom_address;
	char char_eeprom_address[20];
	char crystal_temp[10];   			//    
	char first_sensor_temp[10];
//     EEPROM    LCD
	geted_eeprom_address = getAddrFromEEPROM( 0x5A );
	sprintf(char_eeprom_address, "%x", (uint8_t) geted_eeprom_address);
	sendStr("addr value:", 3, 0);
	sendStr (char_eeprom_address, 3, 14 );

	setAddrToEEPROM (0x5A , 0xA); //   
//       LCD
	geted_eeprom_address = getAddrFromEEPROM( 0x5A );
	sprintf(char_eeprom_address, "%x", (uint8_t) geted_eeprom_address);
	sendStr("new addr :", 4, 0);
	sendStr (char_eeprom_address, 4, 14 );



	while(1){
//        
		 getTemp_Mlx90614_CharArray ( 0x5A,  MLX90614_TA, crystal_temp );
		 sendStr( "Crystal Temp :", 1, 0 );
		 sendStr( crystal_temp, 1, 14 );
    
		delay_s(1);
    
		 getTemp_Mlx90614_CharArray ( 0x5A,  MLX90614_TOBJ_1, first_sensor_temp );
		 sendStr( "Sensor Temp  :", 2, 0 );
		 sendStr( first_sensor_temp, 2, 14 );
    
			delay_s(1);
	}
}

main.h

#ifndef CORE_INC_MAIN_H_
#define CORE_INC_MAIN_H_

#include "stm32f1xx.h"
#include "clk_ini.h" //  
#include "delay.h"		//  
#include "lcd_20x4.h" //     LCD A2004
#include "mlx90614.h" //    

#endif /* CORE_INC_MAIN_H_ */

:

In conclusion, complete project listings

mlx90614.h
#ifndef I2C_DEVICES_I2C_H_
#define I2C_DEVICES_I2C_H_

#include "stm32f1xx.h"
#include <stdio.h>
#include "delay.h"

#define F_APB1 36 //   APB1
#define TPCLK1 ( 1000/F_APB1 ) //   APB1 ns. ~ 28
#define CCR_VALUE ( 10000 /(TPCLK1 * 2 ) ) //   CCR  36  ~ 179
#define TRISE_VALUE ( 1000 / TPCLK1)

//---------------- RAM addresses --------------------------------------------
#define MLX90614_RAW_IR_1 0x04		//    
#define MLX90614_RAW_IR_2 0x05
#define MLX90614_TA 0x06			//   
#define MLX90614_TOBJ_1 0x07		//     
#define MLX90614_TOBJ_2 0x08		//     

//--------------- EEPROM addresses ------------------------------------------
#define MLX90614_TO_MAX 0x00
#define MLX90614_TO_MIN 0x01
#define MLX90614_PWM_CTRL 0x02
#define MLX90614_TA_RANGE 0x03
#define MLX90614_EMISSIVITY 0x04
#define MLX90614_CONFIG_REGISTER_1 0x05
#define MLX90614_SMBUS_ADDRESS 0x0E // LSByte only
#define MLX90614_ID_NUMBER_1 0x1C
#define MLX90614_ID_NUMBER_2 0x1D
#define MLX90614_ID_NUMBER_3 0x1E
#define MLX90614_ID_NUMBER_4 0x1F

//--------------- Commands ------------------------------------------------
#define MLX90614_RAM_ACCESS 0 			//   RAM
#define MLX90614_EEPROM_ACCESS 0x20 	//   EEPROM
#define MLX90614_READ_FLAGS 0xF0 		//  
#define MLX90614_ENTER_SLEEP_MODE 0xFF 	//  
#define MLX90614_READ 1					//    
#define MLX90614_WRITE 0				//    

void mlx90614Init( void );
double getTemp_Mlx90614_Double( uint16_t address, uint8_t ram_address );
void getTemp_Mlx90614_CharArray( uint16_t address, uint8_t ram_address, char* buf );

uint16_t getAddrFromEEPROM( uint16_t address );
int setAddrToEEPROM ( uint16_t address, uint16_t new_address );

uint16_t readEEPROM( uint16_t address, uint16_t eeprom_address );
void writeEEPROM ( uint16_t address, uint16_t eeprom_address, uint16_t data );

#endif /* I2C_DEVICES_I2C_H_ */

mlx90614.c
#include "mlx90614.h"

/********************************************************************************************
 *   I2C      MLX90614   					*
 * 																		 					*
 ********************************************************************************************/

 void mlx90614Init(void){

	 delay_ms(120);								//        

RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;				//  
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;				//  i2c1

GPIOB->CRL |= GPIO_CRL_MODE6 | GPIO_CRL_MODE7;	//  50 
GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7; 	//  -  

I2C1->CR2 &= ~I2C_CR2_FREQ; 					//       APB1
I2C1->CR2 |= F_APB1; 							//    APB1    I2C 
I2C1->CR1 &= ~I2C_CR1_PE; 						//   I2C    CCR
I2C1->CCR &= ~I2C_CCR_CCR;
I2C1->CCR |=  CCR_VALUE;
I2C1->TRISE |=  TRISE_VALUE;

I2C1->CR1 |= I2C_CR1_ENPEC; 					//   PEC
I2C1->CR1 |= I2C_CR1_PE;						//   I2C
I2C1->CR1 |= I2C_CR1_ACK; 						//  ACK

}

/********************************************************************************************
 *      .    double. 					*
 * 																		  					*
 *  : 														   					*
 * address - 				  MLX90614						   					*
 * 																		   					*
 * ram_address RAM-   ( .   .h  ) : 		   					*
 * 																		   					*
 * 	MLX90614_TA - 		  					   					*
 * 	MLX90614_TOBJ_1 - 	   					   					*
 * 	MLX90614_TOBJ_2 - 	   					  					*
  *******************************************************************************************/

double getTemp_Mlx90614_Double( uint16_t address,
								uint8_t ram_address){

	 uint16_t	temp ; 						// 
	 uint8_t	temp_lsb ;					//   
	 double temp_result ; 					//   
	 double temp_double ;					// ,    double

	 address = address<<1; 						//     (  
	 	 	 	 	 	 	 	 	 	 	 	//   1-  /)
	 I2C1->CR1 |= I2C_CR1_START;
	 while (!(I2C1->SR1 & I2C_SR1_SB)){}

	 (void) I2C1->SR1;

	 I2C1->DR = address | MLX90614_WRITE; 		//   ,   MLX90614
	 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

	 (void) I2C1->SR1;
	 (void) I2C1->SR2;

	 I2C1->DR= ram_address;						//   RAM   MLX90614
	 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

	 I2C1->CR1 |= I2C_CR1_START;				//  
	 while (!(I2C1->SR1 & I2C_SR1_SB)){}

	 (void) I2C1->SR1;

	 I2C1->DR = address | MLX90614_READ;			//     
	 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

	 (void) I2C1->SR1;
	 (void) I2C1->SR2;

	 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

	 temp_lsb = I2C1->DR;							//   

	 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

	 temp = I2C1->DR;								//   

	 I2C1->CR1 |= I2C_CR1_STOP;

	 temp = (temp & 0x007F) << 8;					//   ,    
	 temp |= temp_lsb;
	 temp_double = (double) temp; 					//    double
	 temp_result =  ((temp_double * 0.02)- 0.01 );	//    
	 temp_result = temp_result - 273.15; 			//    . 



return temp_result;


 }


/********************************************************************************************
 *   ,   ,   char   .  *
 * 																							*
 *  : 																			*
 * address - 			  MLX90614												*
 * 																							*
 * ram_address RAM-   ( .   .h  ) : 							*
 * 																							*
 * 	MLX90614_TA - 		  										*
 * 	MLX90614_TOBJ_1 - 	   										*
 * 	MLX90614_TOBJ_2 - 	   										*
 * 																							*
 * 	*buf - 				  													*
 *******************************************************************************************/

void getTemp_Mlx90614_CharArray( uint16_t address, uint8_t ram_address, char* buf){

	double t;
	t = getTemp_Mlx90614_Double(address,ram_address);

	 sprintf(buf, "%.1f",t);

	return ;

}



/********************************************************************************************
 *   EEPROM    											*
 *  :																			*
 * address -  																	*
 * eeprom_address -   EEPROM															*
 * 																							*
 *  :																			*
 *    EEPROM  uint16_t													*
 *																							*
 * ******************************************************************************************/

uint16_t readEEPROM( uint16_t address, uint16_t eeprom_address ){

	 uint16_t	data_msb;
	 uint16_t	data_lsb;
	 uint16_t data_result;

	 address = address<<1; 									//     (    + 1  /)

	 	 I2C1->CR1 |= I2C_CR1_START;
		 while (!(I2C1->SR1 & I2C_SR1_SB)){}

		 (void) I2C1->SR1;

		 I2C1->DR = address | MLX90614_WRITE; 				//   ,   MLX90614
		 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

		 (void) I2C1->SR1;
		 (void) I2C1->SR2;

		 I2C1->DR= eeprom_address | MLX90614_EEPROM_ACCESS;	//   EEPROM  MLX90614
		 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

		 I2C1->CR1 |= I2C_CR1_START;						//  
		 while (!(I2C1->SR1 & I2C_SR1_SB)){}

		 (void) I2C1->SR1;

		 I2C1->DR = address | MLX90614_READ;				//     
		 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

		 (void) I2C1->SR1;
		 (void) I2C1->SR2;

		 //I2C1->CR1 &= ~I2C_CR1_ACK;
		 while (!(I2C1->SR1 & I2C_SR1_RXNE)){};

		 data_lsb = I2C1->DR;								//   

		 while(!(I2C1->SR1 & I2C_SR1_RXNE)){}

		 data_msb = I2C1->DR;									//   


		 I2C1->CR1 |= I2C_CR1_STOP;


		data_result = ((data_msb << 8) | data_lsb) ;//& 0x1F;

		 return data_result;


}

/********************************************************************************************
 *   EEPROM    												    *
 * 																						    *
 *  :																		    *
 * address - 		 														    *
 * eeprom_address -   EEPROM														    *
 * data - 																			    *
 ********************************************************************************************/
void writeEEPROM ( uint16_t address, uint16_t eeprom_address, uint16_t data ){


		 address = address<<1; 									//     (..    + 1  /)

		 	 I2C1->CR1 |= I2C_CR1_START;
			 while (!(I2C1->SR1 & I2C_SR1_SB)){}

			 (void) I2C1->SR1;

			 I2C1->DR = address | MLX90614_WRITE; 				//   ,   MLX90614
			 while (!(I2C1->SR1 & I2C_SR1_ADDR)){}

			 (void) I2C1->SR1;
			 (void) I2C1->SR2;

			 I2C1->DR= eeprom_address | MLX90614_EEPROM_ACCESS;	//   EEPROM  MLX90614
			 while (!(I2C1->SR1 & I2C_SR1_TXE)){}

			 I2C1->DR =  ( uint8_t ) ( data & 0x00FF );			//   

			 while(!(I2C1->SR1 & I2C_SR1_BTF)){}

			 I2C1->DR = ( uint8_t ) ( data >> 8 )	;			//   
			 while(!(I2C1->SR1 & I2C_SR1_BTF)){}

			 I2C1->CR1 |= I2C_CR1_PEC;							//  PEC
			 I2C1->CR1 |= I2C_CR1_STOP;


			 return ;
}

/********************************************************************************************
 *     EEPROM															*
 * 																							*
 *  :																			*
 * address -  																	*
 *																							*
 *  :																			*
 *    uint8_t																	*
 *  																						*
 *******************************************************************************************/

uint16_t getAddrFromEEPROM ( uint16_t address ){

	uint16_t addr_eeprom;
	addr_eeprom = readEEPROM( address, MLX90614_SMBUS_ADDRESS );

	return addr_eeprom;

}

/********************************************************************************************
 *      EEPROM													*
 * 																							*
 *  :																			*
 * address - 		  															*
 * new_address -	 															*
 * 																							*
 *  1 - / 0 - 														*
 ********************************************************************************************/

int setAddrToEEPROM ( uint16_t address, uint16_t new_address ){

	uint16_t addr;

	writeEEPROM ( address, MLX90614_SMBUS_ADDRESS, 0x0); //  
	delay_ms(10);
	writeEEPROM (address, MLX90614_SMBUS_ADDRESS, new_address ); //   
	delay_ms(10);
	addr = readEEPROM ( address, MLX90614_SMBUS_ADDRESS ); //   

	if ( addr == new_address){
		return 1;
	}

	else return 0;

}

clk_ini.h
#ifndef INC_CLK_INI_H_
#define INC_CLK_INI_H_
#include "stm32f1xx.h"

int clk_ini(void);
#endif /* INC_CLK_INI_H_ */

clk_ini.c
#include "clk_ini.h"

int clk_ini(void){

	RCC->CR |= (1 << RCC_CR_HSEON_Pos);

	__IO int startCounter;
	for(startCounter = 0; ; startCounter++){

		if(RCC->CR & (1 << RCC_CR_HSERDY_Pos)){

			break;
		}// if

		if(startCounter > 0x1000){

			RCC->CR &= ~(1 << RCC_CR_HSEON_Pos);
			return 1;
		}
	}// for

	RCC->CFGR |= (0x07 << RCC_CFGR_PLLMULL_Pos) // PLL x9
			 	 |(0x01 << RCC_CFGR_PLLSRC_Pos); // start clocking PLL of HSE

	RCC->CR |= (1 << RCC_CR_PLLON_Pos);

	for(startCounter = 0; ; startCounter++){

		if(RCC->CR & (1 << RCC_CR_PLLRDY_Pos)){

			break;
		}//if

		if(startCounter > 0x1000){

			RCC->CR &= ~(1 << RCC_CR_HSEON_Pos);
			RCC->CR &= ~(1 << RCC_CR_PLLON_Pos);
			return 2;
		}// if
	}// for

	////////////////////////////////////////////////////////////
	  // FLASH  
	  ////////////////////////////////////////////////////////////

	  // 2    Flash
	  //       48 MHz < SYSCLK <= 72 MHz
	  FLASH->ACR |= (0x02<<FLASH_ACR_LATENCY_Pos);

	  //
	  RCC->CFGR |= (0x00<<RCC_CFGR_PPRE2_Pos) //  APB2  1
	            | (0x04<<RCC_CFGR_PPRE1_Pos) //  APB1  2
	            | (0x00<<RCC_CFGR_HPRE_Pos); // AHB 


	  RCC->CFGR |= (0x02<<RCC_CFGR_SW_Pos); //    PLL

	  //,  
	  while((RCC->CFGR & RCC_CFGR_SWS_Msk) != (0x02<<RCC_CFGR_SWS_Pos))
	  {
	  }

	  // ,   
	  //  
	  //  RC-
	  //  
	  RCC->CR &= ~(1<<RCC_CR_HSION_Pos);

	  //   
	  //   
	  // PLL  .
	  //

	return 0;
}

delay.h
#ifndef DELAY_DELAY_H_
#define DELAY_DELAY_H_

#include "stm32f1xx.h"

#define F_CPU 72000000UL
#define US F_CPU/1000000
#define MS F_CPU/1000
#define SYSTICK_MAX_VALUE 16777215
#define US_MAX_VALUE SYSTICK_MAX_VALUE/(US)
#define MS_MAX_VALUE SYSTICK_MAX_VALUE/(MS)


void delay_us(uint32_t us); //  233 
void delay_ms(uint32_t ms); //  233 
void delay_s(uint32_t s);

delay.c
#include "delay.h"


/*      */

void delay_us(uint32_t us){ //  233 016 

	if (us > US_MAX_VALUE || us == 0)
		return;

	SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; //     0
	SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; //    
	SysTick->LOAD = (US * us-1); //       
	SysTick->VAL = 0; //     SYST_CVR
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //  

	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); //    COUNFLAG   SYST_CSR

	SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;	//   COUNTFLAG
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //  
	return;

}

void delay_ms(uint32_t ms){ //  233 

	if(ms > MS_MAX_VALUE || ms ==0)
		return;

	SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
	SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
	SysTick->LOAD = (MS * ms);
	SysTick->VAL = 0;
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

	while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));

	SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
return;

}

void delay_s(uint32_t s){

	for(int i=0; i<s*5;i++) delay_ms(200);
	return;
}

lcd_20x4.h
#ifndef LCD_LCD_20X4_2004A_LCD_20X4_H_
#define LCD_LCD_20X4_2004A_LCD_20X4_H_

#include "stm32f1xx.h"
#include "delay.h"

// display commands

#define CLEAR_DISPLAY 0x1
#define RETURN_HOME 0x2
#define ENTRY_MODE_SET 0x6 // mode cursor shift rihgt, display non shift
#define DISPLAY_ON 0xC // non cursor
#define DISPLAY_OFF 0x8
#define CURSOR_SHIFT_LEFT 0x10
#define CURSOR_SHIFT_RIGHT 0x14
#define DISPLAY_SHIFT_LEFT 0x18
#define DISPLAY_SHIFT_RIGHT 0x1C
#define DATA_BUS_4BIT_PAGE0 0x28
#define DATA_BUS_4BIT_PAGE1 0x2A
#define DATA_BUS_8BIT_PAGE0 0x38
#define SET_CGRAM_ADDRESS 0x40 // usage address |= SET_CGRAM_ADDRESS
#define SET_DDRAM_ADDRESS 0x80

//     ODR
#define PIN_RS 0x1
#define PIN_EN 0x2
#define PIN_D4 0x1000
#define PIN_D5 0x2000
#define PIN_D6 0x4000
#define PIN_D7 0x8000

#define     LCD_PORT               	GPIOB
#define		LCD_ODR 				LCD_PORT->ODR

#define     LCD_PIN_RS()     		LCD_PORT->CRL |= GPIO_CRL_MODE0_0;\
									LCD_PORT->CRL &= ~GPIO_CRL_CNF0; // PB0   -,  10 

#define     LCD_PIN_EN()            LCD_PORT->CRL |= GPIO_CRL_MODE1_0;\
									LCD_PORT->CRL &= ~GPIO_CRL_CNF1;        // PB1

#define     LCD_PIN_D4()            LCD_PORT->CRH |= GPIO_CRH_MODE12_0;\
									LCD_PORT->CRH &= ~GPIO_CRH_CNF12;          // PB7

#define     LCD_PIN_D5()           	LCD_PORT->CRH |= GPIO_CRH_MODE13_0;\
									LCD_PORT->CRH &= ~GPIO_CRH_CNF13;      // PB6

#define     LCD_PIN_D6()            LCD_PORT->CRH |= GPIO_CRH_MODE14_0;\
									LCD_PORT->CRH &= ~GPIO_CRH_CNF14;         // PB5

#define     LCD_PIN_D7()            LCD_PORT->CRH |= GPIO_CRH_MODE15_0;\
									LCD_PORT->CRH &= ~GPIO_CRH_CNF15;         // PB10

#define     LCD_PIN_MASK   (PIN_RS | PIN_EN | PIN_D7 | PIN_D6 | PIN_D5 | PIN_D4) // 0b0000000011110011    

void lcd_2004a_init(void); //     
void sendByte(char byte, int isData);
void sendStr(char *str, int row , int position); //  


#endif /* LCD_LCD_20X4_2004A_LCD_20X4_H_ */

lcd_20x4.c
#include "lcd_20x4.h"

//     LCD

void lcdInit(void); //  


void sendByte(char byte, int isData){

	//   
	LCD_ODR &= ~LCD_PIN_MASK;

	if(isData == 1) LCD_ODR |= PIN_RS; //    RS
		else LCD_ODR &= ~(PIN_RS);		   //   RS

	//   E
		LCD_ODR |= PIN_EN;

	//     
	if(byte & 0x80) LCD_ODR |= PIN_D7;
	if(byte & 0x40) LCD_ODR |= PIN_D6;
	if(byte & 0x20) LCD_ODR |= PIN_D5;
	if(byte & 0x10) LCD_ODR |= PIN_D4;
	
	LCD_ODR &= ~PIN_EN; //   

	//     RS
	LCD_ODR &= ~(LCD_PIN_MASK & ~PIN_RS);

	//   E

		LCD_ODR |= PIN_EN;
	//     
	if(byte & 0x8) LCD_ODR |= PIN_D7;
	if(byte & 0x4) LCD_ODR |= PIN_D6;
	if(byte & 0x2) LCD_ODR |= PIN_D5;
	if(byte & 0x1) LCD_ODR |= PIN_D4;

	//   

	LCD_ODR &= ~(PIN_EN);
	delay_us(40);


	return;
}

//               50 

void lcd_2004a_init(void){

//----------------------  ----------------------------------------------------

	if(LCD_PORT == GPIOB) RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
	else if (LCD_PORT == GPIOA) RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	else return;

//---------------------    LCD-----------------------------------------------------

		LCD_PIN_RS();
		LCD_PIN_EN();
		LCD_PIN_D7();
		LCD_PIN_D6();
		LCD_PIN_D5();
		LCD_PIN_D4();


		lcdInit();






	return ;
}

//---------------------  -----------------------------------------------------------
void lcdInit(void){



			delay_ms(200); //    

			sendByte(0x33, 0); //      0011
			delay_us(120);

			sendByte(0x32, 0); //      00110010
			delay_us(40);

			sendByte(DATA_BUS_4BIT_PAGE0, 0); //   4 
			delay_us(40);
			sendByte(DISPLAY_OFF, 0); //  
			delay_us(40);
			sendByte(CLEAR_DISPLAY, 0); //  
			delay_ms(2);
			sendByte(ENTRY_MODE_SET, 0); //      
			delay_us(40);
			sendByte(DISPLAY_ON, 0);//     
			delay_us(40);


	return ;
}

void sendStr( char *str, int row , int position ){

	char start_address;

	switch (row) {

	case 1:
		start_address = 0x0; // 1 
		break;

	case 2:
		start_address = 0x40; // 2 
		break;

	case 3:
		start_address = 0x14; // 3 
		break;

	case 4:
		start_address = 0x54; // 4 
		break;

	}

	start_address += position; //       

	sendByte((start_address |= SET_DDRAM_ADDRESS), 0); //         DDRAM

	delay_ms(4);
	while(*str != '\0'){

		sendByte(*str, 1);
		str++;


	}// while
}




All Articles