Stm32 i²c Communication [Operation Register + library function]

Source: Internet
Author: User
Tags ack switches
The I²c bus is designed by NXP (formerly Philips) and has a very concise physical layer definition with the following characteristics: As long as the two bus line: A serial data line SDA, a serial clock line SCL; Each device connected to the bus can have a unique address and a simple host From the system software to set the address, the host can act as a host transmitter or host receiver; it is a true multi-host bus, and if two or more hosts are initialized at the same time, data transmission can be prevented by conflict detection and arbitration; Serial 8-bit bidirectional data transfer bit rate up to 100kbit/in standard mode s, fast mode up to 400kbit/s, high speed mode up to 3.4mbit/s, the number of ICS connected to the same bus is limited only by the maximum capacitance of the bus 400pF. The typical interface is wired as follows: The I²C protocol is simple: the validity of the dataWhen transmitting data, the SDA line must remain stable at the high-level period of the clock, and the high or low status of SDA can only be changed when the SCL line's clock signal is low. start and stop conditionsThe SCL line is high, and the SDA line switches from high to low, which indicates the starting condition, the SCL line is high, and the SDA line switches from low to high, which indicates the stop condition. byte formatEach byte sent to the SDA line must be 8 bits, and the number of bytes that can be sent per transmission is unrestricted. A response bit must be processed after each byte. Answer ResponseThe data transmission must be responsive, and the associated response clock pulses are generated by the host.           During the clock pulse of the response the transmitter releases the SDA line (high).        During the response clock pulse, the receiver must pull the SDA line low so that it remains stable at low levels during the high level of the clock pulse. This means that the main device will receive an answer bit (low level) after sending one byte of data, and send a low level after receiving a byte from the device. addressing Mode (7-bit address mode)The first byte of the header 7 bits makes up the slave address, and the lowest bit (LSB) is the 8th bit, which determines the normal and 7-bit address format direction of the transmission with the repeating start condition. The lowest bit of the first byte is "0", indicating that the host writes information to the selected slave, and "1" indicates that the master is reading the information to the slave machine. When an address is sent, each device in the system compares the first 7 bits to its own address after the starting condition, and if the device determines that it is addressed by the host, the slave receiver or slave transmitter is determined by the r/w bit. arbitrationI²c is the host bus, each device can become a host, but only one host at any one time. The stm32 has at least one I²c interface, which provides multi-host capabilities to enable timing, protocol, quorum, and timing functions for all I²C buses, supports both standard and fast transmission modes, and is compatible with SMBus 2.0.

In this experiment, the direct operation Register is implemented to write and read the EEPROM at24c02 of the I²C bus structure. AT24C02 related Operations SeeSingle-chip microcomputer read EEPROM (AT24C02).The library functions are used to transmit and receive data between the two i²c analog devices using STM32 and to view data exchange through the serial port. Direct Operation Register   First need to configure the I²c interface clock, the relevant registers are as follows:   I2C_CR2 register low five-bit:      FREQ[5:0]:I2C module clock frequency, The correct input clock frequency must be set to produce the correct timing, allowing the range between 2~36mhz:     000000: Disable       000001: Disable       000010:2mhz             100100:36mhz       Greater than 100100: disabled.     To set the input clock for the I²C device, this example uses the clock on the PLCK1 bus so that it is 36Mhz;   Clock Control register (I2C_CCR) Low 12-bit: ccr[11:0]: Clock control divider factor in fast/Standard mode (main mode), which is used to set the SCL clock in main mode. In I²c Standard mode or SMBus mode:         thigh = CCRxTPCLK1          tlow = CCRxTPCLK1           Clock period is T = thigh + tlow;   For example: In standard mode, FREQR = 36 is 36Mhz, the frequency of 200kHz SCL is generated                 Clock control divider factor  = freqr/2/f    F for the desired frequency     Configure the clock, also need to configure the native address, I²C support 7-bit address and 10-bit address, Here is a 7-bit address: its own address register 1 (I2C_OAR1) [7:1]: The interface address, the address of the 7~1 bit.   Other related operations see Code, withDetailed comments: (System.h and  stm32f10x_it.h  and other related code reference   STM32 Direct Operation Register Development environment configuration)   USER/MAIN.C

#include <stm32f10x_lib.h> #include "system.h" #include "usart.h" #include "i2c.h" #define LED1 paout (4) #define

LED2 paout (5) #define LED3 paout (6) #define LED4 paout (7) void gpio_init (void); 			 			  int main (void) {Rcc_init (9);

	system clock Settings Usart1_init (72,9600);	  Nvic_init (1,0,i2c1_ev_irqchannel,4);	  Set preemption priority to 1, response priority to 0, interrupt group to 4 nvic_init (0,0,i2c1_er_irqchannel,4);

	Set I²c error interrupt preemption priority to 0 gpio_init ();							  I2c_init (0x30);

	Set the I2C1 address to 0x30 I2c_start ();		
while (1);    		} void Gpio_init (void) {Rcc->apb2enr |= 1<<2;    		Enable Porta clock Rcc->apb2enr |= 1<<3; 	


	Enable to PORTB the clock; 		GPIOA-&GT;CRL &= 0x0000ffff; 


	Pa0~3 is set to float input, pa4~7 is set to push-pull output gpioa->crl |= 0x33334444;    	GPIOB-&GT;CRL &= 0x00ffffff;		PB6 I2C1_SCL, PB7 i2c1_sdl gpiob->crl |= 0xff000000;   	Multiplexed open-Drain output//usart1 serial I/O settings Gpioa CRH &= 0xfffff00f;	  

Set USART1 TX (pa.9) for the second function push-pull, 50mhz;rx (pa.10) for float input Gpioa, CRH |= 0x000008b0;
 }
User/stm32f10x_it.c
#include "stm32f10x_it.h" #include "system.h" #include "stdio.h" #include "i2c.h" #define LED1 paout (4) #define LED2 Paou  T (5) #define LED3 paout (6) #define LED4 paout (7) #define ADDRS_R 0XA1//Read operation address #define ADDRS_W 0xA0//write operation address U8				  Go = 0;

	Action steps mark void I2c1_ev_irqhandler (void)//i2c1 Event Interrupt {u16 clear = 0; if (I2C1-SR1 & 1<<0)//Sent starting condition, write data register operation will clear that bit {printf ("\ r \ n i2c1 start.

		\ r \ n ");		   Switch (GO) {case 0:{i2c_write (ADDRS_W);
			Writes the slave address, writes the command operation address break;		   } Case 1:{I2c_write (ADDRS_W);
			Writes the slave address, writes the command operation address break;		   } Case 2:{I2c_write (addrs_r);
		   Write the slave address, read data operation address break; }}} if (I2c1-SR1 & 1<<1)//slave address sent {printf ("\ r \ n i2c1 has send address:
		\ r \ n ");	Clear = i2c1-SR2;
			Read SR2 can clear the bit interrupt switch (GO) {case 0:{i2c_write (0x01);//write the EEPROM unit address to write to break;
		} Case 1:{I2c_write (0x01);//write to the address of the EEPROM unit to be written to break;	} Case 2:{delay (100000);  printf ("\ r \ n Read 0x%X from At24c02, Address 0x01.
			 	\ r \ n ", I2c_read ());
				I2c_stop ();
		   Break }}} if (I2c1-SR1 & 1<<2)//Bytes send end send address byte, this interrupt is not triggered {//printf ("\ r \ n i2c1 send byte success. .
		\ r \ n ");			Switch (GO) {case 0:{i2c_write (0x86);  Write data printf ("\ r \ n Write 0x%X to At24c02, Address 0x01.)			
				\ r \ n ", 0x86);
	
				I2c_stop ();
				Delay (10000);
				Go = 1; 
				I2c_start ();
			Break
				} Case 1:{delay (10000);
				Go = 2;
				I2c_start ();
			Break
		   } Case 2:{break;
	}}} delay (100000);

   	LED3 = 1;			I2C1, CR2 &= ~ (1<<9);
	Event interrupt closed} void I2c1_er_irqhandler (void)//i2c1 Error Interrupt {delay (100000);	

	LED4 = 1; if (I2C1-&GT;SR1 & 1<<10)//answer failed {printf ("\ r \ n ACK ERROR:

		\ r \ n ");		I2C1-&GT;SR1 &=~ (1&LT;&LT;10); Clear interrupts} if (I2C1-&GT;SR1 & 1<<14)//timeout {printf ("\ r \ n Timeout: \ r \ n ");

		I2C1-&GT;SR1 &=~ (1<<14); Clear interrupts} if (I2C1-&GT;SR1 & 1<<11)//overload/Under load {printf ("\ r \ n Overrun/underrun.
		\ r \ n ");		I2C1-&GT;SR1 &=~ (1&LT;&LT;11); Clear interrupts} if (I2C1-&GT;SR1 & 1<<9)//quorum lost {printf ("\ r \ n arbitration lost.
		\ r \ n ");		I2C1-&GT;SR1 &=~ (1<<9); Clear interrupts} if (I2C1-&GT;SR1 & 1<<8)//Bus error {printf ("\ r \ n Bus Error:
		\ r \ n ");		I2C1-&GT;SR1 &=~ (1<<8);
 Clear Interrupt}}
Library/src/i2c.c
#include "i2c.h" void I2c_init (U16 Addr) {RCC, apb1enr |= 1<<21;			Open i2c1 clock//RCC, Apb1enr |= 1<<22;			Open i2c2 clock rcc->apb1rstr |= 1<<21;			Reset i2c1 rcc->apb1rstr &= ~ (1<<21);			Reset End i2c1//rcc->apb1rstr |= 1<<22;    			Reset I2c2//i2c1, CR1 |= 1<<15;				Reset register//I2C Module clock frequency, 2~36mhz between i2c1 and CR2 |= 36; 000000: Disable 000001: Disable 000010:2mhz ...				100100:36mhz i2c1, CCR |= 0<<15;				I²c Main Mode 0: Standard mode i²c 1: Fast mode i²c//i2c1-and CCR |= 1<<14;				Duty ratio in quick mode 0 Tlow/thigh = 2 1 Tlow/thigh = 16/9//Get 200kHz frequency i2c1, CCR |= 90<<0;				Clock control divide factor = pclk1/2/f F for desired frequency//main mode Max rise time i2c1-Trise |= 37;

	The maximum allowable SCL rise time is 1000ns, so trise[5:0] must be written (1us/(1/36) US = 36+1).				I2C1, CR1 |= 1<<10;				Open ACK answer, return a byte after receiving a reply i2c1, CR1 |= 1<<6;				Broadcast call enable I2C1-OAR1 |= 0<<15; Addressing mode 1 response 10-bit address 0 response 7-bit address i2c1-OAR1 |= 1<<14;				Must always be kept by the software at 1 i2c1-OAR1 |= Addr <<1;  			Set interface address 7~1 bit//i2c1, OAR1 |= 0;				When setting the 10-bit address mode, address No. 0//i2c1-OAR1 |= 0<<8;				When setting the 10-bit address mode, address 9th to 8th//I2C1-CR2 |= 1<<10;				Buffer interrupt Enable I2C1-CR2 |= 1<<9;				Event interrupt Enable I2C1-CR2 |= 1<<8;				Error interrupt enable I2C1-CR1 |= 1<<0;				Open i2c1} void I2c_start () {i2c1, CR1 |= 1<<8;				I2C1 produces a starting condition} void I2c_stop () {i2c1-CR1 |= 1<<9;

I2C1 produces a stop condition} void I2c_write (U8 data) {i2c1-DR = data;} U8 I2c_read () {while (!) (		I2C1, SR1 & 1<<6));
Received data marker return I2C1-a DR;		
} void I2c_end ()//off I²c {i2c1, CR1 &= ~ (1<<0);
 }
Library/inc/i2c.h
#include <stm32f10x_lib.h>

void I2c_init (U16 Addr);	

void  i2c_start (void);
void  i2c_stop (void);
void  I2c_write (U8 data);
U8    i2c_read (void);
void  i2c_end (void);
The serial port receives the data as follows: I2c1 Start.   I2C1 has send address.    Write 0x86 to At24c02, Address 0x01.   I2C1 Start.   I2C1 has send address.   I2C1 Start.   I2C1 has send address. Read 0x86 from At24c02, Address 0x01. Library function OperationsMain.c
#include "stm32f10x.h" #include "stdio.h" #define printf_on 1 void rcc_configuration (void);
void gpio_configuration (void);
void usart_configuration (void);
void i2c_configuration (void);


void nvic_configuration (void);   U8 i2c1_address = 0x30;

7-bit i²c address u8 i2c2_address = 0x31;
#define SIZE 4 vu8 i2c1_buffer_tx[size] = {1,2,3,4};

Vu8 I2c2_buffer_rx[size] = {0};

U32 buffersize = Size;
	int main (void) {rcc_configuration ();
	Gpio_configuration ();
	Usart_configuration ();
	I2c_configuration ();

	Nvic_configuration ();

	I2c_generatestart (i2c1,enable);	
while (1);

	} void I2c_configuration (void) {i2c_inittypedef i2c_initstructure;
	I2c_initstructure.i2c_mode = I2C_MODE_I2C;
	I2c_initstructure.i2c_dutycycle = i2c_dutycycle_2;
	I2c_initstructure.i2c_ownaddress1 = i2c1_address;
	I2c_initstructure.i2c_ack = i2c_ack_enable;
	i2c_initstructure.i2c_acknowledgedaddress = I2c_acknowledgedaddress_7bit;
	I2c_initstructure.i2c_clockspeed = 200000;

I2c_init (i2c1,&i2c_initstructure);	I2c_initstructure.i2c_mode = I2C_MODE_I2C;
	I2c_initstructure.i2c_dutycycle = i2c_dutycycle_2;
	I2c_initstructure.i2c_ownaddress1 = i2c2_address;
	I2c_initstructure.i2c_ack = i2c_ack_enable;
	i2c_initstructure.i2c_acknowledgedaddress = I2c_acknowledgedaddress_7bit;
	I2c_initstructure.i2c_clockspeed = 200000;


	I2c_init (i2c2,&i2c_initstructure); I2c_itconfig (i2c1,i2c_it_evt|
	i2c_it_buf,enable); I2c_itconfig (i2c2,i2c_it_evt|
	
	i2c_it_buf,enable);
	I2c_cmd (i2c1,enable);
I2c_cmd (i2c2,enable);

	} void Nvic_configuration (void) {nvic_inittypedef nvic_initstructure;

	Nvic_prioritygroupconfig (nvic_prioritygroup_1);
	Nvic_initstructure.nvic_irqchannel = I2C1_EV_IRQN;
	nvic_initstructure.nvic_irqchannelpreemptionpriority = 1;
	nvic_initstructure.nvic_irqchannelsubpriority = 0;
	Nvic_initstructure.nvic_irqchannelcmd = ENABLE;

	Nvic_init (&nvic_initstructure);
	Nvic_initstructure.nvic_irqchannel = I2C2_EV_IRQN;
	nvic_initstructure.nvic_irqchannelpreemptionpriority = 0; Nvic_initstruCture.
	nvic_irqchannelsubpriority = 0;
	Nvic_initstructure.nvic_irqchannelcmd = ENABLE;
Nvic_init (&nvic_initstructure);

 	} void Gpio_configuration (void) {gpio_inittypedef gpio_initstructure;

  	Gpio_initstructure.gpio_speed = Gpio_speed_50mhz; Gpio_initstructure.gpio_pin = gpio_pin_6|
  	gpio_pin_7;			
  	Gpio_initstructure.gpio_mode = Gpio_mode_af_od; 

  	Gpio_init (Gpiob, &gpio_initstructure); Gpio_initstructure.gpio_pin = gpio_pin_10|		
 	Gpio_pin_11;
  	Gpio_initstructure.gpio_speed = Gpio_speed_50mhz;	
  	Gpio_initstructure.gpio_mode = Gpio_mode_af_od; 


  	Gpio_init (Gpiob, &gpio_initstructure);
  	Gpio_initstructure.gpio_pin = Gpio_pin_9;			
  	Gpio_initstructure.gpio_mode = gpio_mode_af_pp; 
	
  	Gpio_init (Gpioa, &gpio_initstructure);
  	Gpio_initstructure.gpio_pin = gpio_pin_10;			
  	Gpio_initstructure.gpio_mode = gpio_mode_in_floating; 
Gpio_init (Gpioa, &gpio_initstructure); } void Rcc_configuration (void) {/* Defines an enumeration type variable Hsestartupstatus */ErrorStatus Hsestartupstatus;
  	/* Reset system Clock Settings */Rcc_deinit ();
  	/* Open hse*/rcc_hseconfig (rcc_hse_on);
	/* Wait for the HSE to start vibrating and stabilize */hsestartupstatus = Rcc_waitforhsestartup (); /* To determine if the HSE is successful, then enter if () internal */if (hsestartupstatus = = SUCCESS) {/* Select HCLK (AHB) clock source for SYSCLK 1 */Rcc_hclkcon 
    	Fig (RCC_SYSCLK_DIV1); 
    	/* Select PCLK2 Clock source for HCLK (AHB) 1/rcc_pclk2config (RCC_HCLK_DIV1);
    	/* Select PCLK1 Clock source for HCLK (AHB) 2/Rcc_pclk1config (RCC_HCLK_DIV2);
    	/* Set FLASH delay period of 2 */flash_setlatency (flash_latency_2);
    	/* Enable FLASH prefetch cache */Flash_prefetchbuffercmd (flash_prefetchbuffer_enable);
    	/* Select Phase-locked loop (PLL) clock source for HSE 1, double frequency 9, the PLL output frequency is 8MHz * 9 = 72MHz */rcc_pllconfig (RCC_PLLSOURCE_HSE_DIV1, rcc_pllmul_9);
    	/* Enable PLL */Rcc_pllcmd (enable);
    	/* Wait for the PLL output to stabilize */while (rcc_getflagstatus (rcc_flag_pllrdy) = = RESET);
    	/* Select SYSCLK Clock source for PLL */Rcc_sysclkconfig (RCC_SYSCLKSOURCE_PLLCLK); /* Wait for the PLL to become SYSCLK clock source */while (Rcc_getsysclksource ()! = 0x08); }/* Open the Gpioa clock on the APB2 bus */Rcc_apb2periphclockcmd (rcc_apb2periph_gpioa| rcc_apb2periph_gpiob|

	Rcc_apb2periph_usart1, ENABLE);

	Rcc_ahbperiphclockcmd (RCC_AHBPERIPH_DMA1, ENABLE); Rcc_apb1periphclockcmd (rcc_apb1periph_i2c1|
	rcc_apb1periph_i2c2,enable); Rcc_apb1periphclockcmd (rcc_apb1periph_pwr| rcc_apb1periph_bkp| Rcc_apb1periph_wwdg|
		
Rcc_apb1periph_spi2, ENABLE);
	} void Usart_configuration (void) {usart_inittypedef usart_initstructure;

	Usart_clockinittypedef usart_clockinitstructure;
	Usart_clockinitstructure.usart_clock = usart_clock_disable;
	Usart_clockinitstructure.usart_cpol = Usart_cpol_low;                                                                                                                                                      
	Usart_clockinitstructure.usart_cpha = Usart_cpha_2edge; Usart_clockinitstructure.usart_lastb
	it = usart_lastbit_disable;

	Usart_clockinit (USART1, &usart_clockinitstructure); Usart_initstructure.usart_baudrate = 9600;
	Usart_initstructure.usart_wordlength = usart_wordlength_8b;
	Usart_initstructure.usart_stopbits = Usart_stopbits_1;
	usart_initstructure.usart_parity = Usart_parity_no;
	Usart_initstructure.usart_hardwareflowcontrol = Usart_hardwareflowcontrol_none; Usart_initstructure.usart_mode = usart_mode_rx|
	Usart_mode_tx;

 	Usart_init (usart1,&usart_initstructure);
Usart_cmd (usart1,enable);
	} #if printf_on int fputc (int ch,file *f) {usart_senddata (USART1, (U8) ch);
	while (Usart_getflagstatus (USART1,USART_FLAG_TC) = = RESET);
return ch;
 } #endif
Stm32f10x_it.c
#include "stm32f10x_it.h" #include "stdio.h" extern u32 buffersize;
extern U8 i2c1_address;

extern U8 i2c2_address;
extern vu8 i2c1_buffer_tx[];
extern vu8 i2c2_buffer_rx[];
Vu32 tx_counter = 0;

Vu32 rx_counter = 0; void I2c1_ev_irqhandler (void) {switch (i2c_getlastevent (i2c1)) {case I2c_event_master_mode_select://Sent start condition {I	
			2c_send7bitaddress (I2c1,i2c2_address,i2c_direction_transmitter);
		Break } Case i2c_event_master_transmitter_mode_selected://Sent slave address {printf ("\ r \ n \ i2c1 has send data%d \ r \ n", I2c1_bu
			Ffer_tx[rx_counter]);
			I2c_senddata (i2c1,i2c1_buffer_tx[tx_counter++]);
		Break } Case i2c_event_master_byte_transmitted://The first data has been sent {if (tx_counter<buffersize) {printf ("\ r \ n the i2c1
				has send data%d \ r \ n ", I2c1_buffer_tx[rx_counter]);   				

			I2c_senddata (i2c1,i2c1_buffer_tx[tx_counter++]);
				}else{i2c_generatestop (i2c1,enable); I2c_itconfig (i2c1,i2c_it_evt|  i2c_it_buf,disable);
		Count the number of sent} break; } defAult: {break;} }} void I2c2_ev_irqhandler (void) {switch (i2c_getlastevent (I2C2)) {case i2c_event_slave_receiver_address_matched:
		received a matching address data {break;  } Case i2c_event_slave_byte_received://Receive Data {if (Rx_counter < buffersize) {I2c2_buffer_rx[rx_counter]
				= I2c_receivedata (I2C2); printf ("\ r \ n The I2C2 has received data%d \ r \ n", i2c2_buffer_rx[rx_counter++]);
		Count the number of received} break;
			} Case i2c_event_slave_stop_detected://Receive End condition {i2c_clearflag (I2c2,i2c_flag_stopf); I2c_itconfig (i2c1,i2c_it_evt|

			i2c_it_buf,disable);
		Break
	} default: {break;}

 }
}
related articles
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.