"STM32 IIc detailed" Stm32 IIC slave mode (interrupt mode to send and receive data)

Source: Internet
Author: User
Tags ack reset
1. Introduction of IIC

The second section of the code will use this part of the content, for IIC, slave can not actively send data, the starting condition is generated by the host.


1.1, the host sends the data flow

1) When the host detects that the bus is "idle" (that is, SDA, SCL Line is high), send a start signal "S", start a communication start
2) The host then sends a command byte. The byte consists of a 7-bit peripheral address and a 1-bit read-write control bit r/w (at this point r/w=0)
3) The corresponding slave receives the command byte and responds to the host feedback ack (ack=0)
4) The host receives the slave's response signal and starts sending the first byte of data
5) return a response signal ACK after receiving data from the machine
6) The host receives the response signal and sends the next data byte
7) When the host sends the last data byte and receives an ACK from the slave, it ends this communication and releases the bus by sending a stop signal to the slave. Communication with the host is also exited after receiving the p signal from the Slave machine


1.2, the host receives the data flow

1) After the host sends the start signal, then sends the command byte (where r/w=1)
2) after the corresponding slave receives the address byte, returns a response signal and sends the data to the host
3) The host receives the data and feeds back a response signal to the slave machine.
4) Send the next data to the host after receiving the answer signal from the machine
5) When the host completes receiving data, sends a "non-response signal (ack=1)" to the slave, and then stops sending after receiving the Ask=1 's non-response signal from the machine.
6) The host sends a non-response signal, and then sends a stop signal, releasing the bus to end the communication


1.3, the processor's I²C module will be described below the situation of the interrupt signal generation

Rx_under when the processor reads the receive buffer through the IC_DATA_CMD register as a null-time position
Rx_over when the receive buffer is filled and data is sent from the peripheral, the data received after the buffer is filled will be lost.
Rx_full is set when the receive buffer reaches or exceeds the threshold specified in the IC_RX_TL register, and the flag bit is automatically cleared when the data falls below the threshold value
Tx_over is set when the send buffer is filled and the processor tries to send additional commands to write the Ic_data_cmd register
Tx_empty is set when the transmit buffer is equal to or less than the threshold specified in the IC_TX_TL register, and the flag bit is automatically cleared when the data is above the threshold value
TX_ABRT when the I²c module is unable to complete a command issued by the processor, there are several reasons:
* No slave answer after sending address byte
* The data sent by the host is not answered after successful address recognition
* When an I²C module can only attempt to send a host command as a Slave
* When the restart function of the module is closed and the function to be completed must be restart function to complete
* High-speed module host code is answered
* START byte is answered
* Module Quorum failure
The contents of the transmit buffer and the receive buffer will be refreshed regardless of when the flag bit is placed.
Activity indicates that the I²C module is active, and this flag will remain until cleared in the following 4 ways:
* Turn off I²c
* Read Ic_clr_activity Register
* Read IC_CLR_INTR Register
* System restart
Even if the I²c module is idle, this flag still needs to be set until it is cleared, as this indicates that there is data being transmitted on the I²C bus

Need to use:

Rd_req when the I²c module acts as a slave and another host attempts to read data from this module
Rx_done when the I²c module sends data as a slave, if the host does not answer it, this occurs when the last byte data is sent by the I²c module, indicating the end of the transmission
The Stop_det indicates that a stop signal is generated on the I²c bus, whether the module is a host or slave
The Start_det indicates that the start signal is generated on the I²c bus, whether the module is a host or slave


2. IIC Slave Interrupt transceiver function

Slave transceiver Function processing
void I2c1_ev_irqhandler (void)
{
__io uint16_t sr1register = 0;
__io uint16_t sr2register = 0;


Sr1register = i2c1->sr1; Get IIC status by reading SR1/2
Sr2register = i2c1->sr2;


Send from Machine
Judging IIC is slave mode-lowest bit (MSL = 0)
if ((Sr2register & 0x0001)! = 0x0001)
{
ADDR: Get slave IIC address success based on state judgment
if ((Sr1register & 0x0002) = = 0x0002)
{
Clear flag, ready to receive data
Sr1register = 0;
Sr2register = 0;
Trcount= 0;
}


TxE: Data can be sent according to status flags
if ((Sr1register & 0x0080) = = 0x0080)
{
Sr1register = 0;
Sr2register = 0;
I2C1->DR =trcount + +;
}

Stopf: Monitoring stop sign
if ((Sr1register & 0x0010) = = 0x0010)
{
I2C1->CR1 |= Cr1_pe_set;
Sr1register = 0;
Sr2register = 0;
Trcount= 5;
}

Time_out
if ((Sr1register & 0x4000) = = 0x4000)
{
I2C1->CR1 |= Cr1_pe_set;
Sr1register = 0;
Sr2register = 0;
}
}

IIC Slave Machine Reception
Judging IIC is slave mode-lowest bit (MSL = 0)
if ((Sr2register &0x0001)! = 0x0001)
{
Received the address sent by the host: (ADDR = 1:EV1)
if ((Sr1register & 0x0002) = = 0x0002)
{
Clear flag, ready to accept data
Sr1register = 0;
Sr2register = 0;
Rx_idx = 0;
}

Receive data (Rxne = 1:ev2)
if ((Sr1register & 0x0040) = = 0x0040)
{
buffer_rx[rx_idx++] = i2c1->dr;
Sr1register = 0;
Sr2register = 0;
}

Monitoring stop conditions (Stopf =1:ev4)
if ((Sr1register & 0x0010) = = 0x0010)
{
I2C1->CR1 |= Cr1_pe_set;
Sr1register = 0;
Sr2register = 0;
Flag_rcvok = 1;
}
}
}


3. Code reference Example

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;
Vu32 show_counter1 = 0;
Vu32 show_counter2 = 0;


I2C1 as host for interrupt receiving slave data
void I2c1_ev_irqhandler (void)
{
show_counter1++;
if (Show_counter1 > 1000000)
{
Show_counter1 = 0;
printf ("\ r \ n \ i2c1 lastevent is%x \ r \ n", I2c_getlastevent (I2C1));
}
Switch (i2c_getlastevent (I2C1))
{
Case I2c_event_master_mode_select://Sent start condition
{
Seven-bit address delivery
I2c_send7bitaddress (i2c1, i2c2_address, i2c_direction_receiver);
printf ("\ r \ n The i2c1 is ready \ r \ n");
Break
}
Case i2c_event_master_receiver_mode_selected://Sent Slave address
{
printf ("\ r \ n \ Slave address is%x \ r \ n", I2c_receivedata (I2C1));
Break
}
Case (I2c_event_master_byte_received | (I2C_FLAG_BTF & 0x0f))://First Data received
{
Turn off the bus before you receive the last byte, or the bus will be locked
I2c_generatestop (i2c1,enable);
printf ("\ r \ n The I2C1 has received data2%x \ r \ n", I2c_receivedata (I2C1));
printf ("\ r \ n \ i2c1 is finish \ r \ n");
Break
}
Case 0X40:
{
Received two of the same data, no this can not be released Rxne
I2c_receivedata (I2C1);
}
Default: {break;}
}
}


I2C2 for sending data from the machine to the host
void I2c2_ev_irqhandler (void)
{
show_counter2++;
if (Show_counter2 > 100000)
{
Show_counter2 = 0;
printf ("\ r \ n \ i2c2 lastevent is%x \ r \ n", I2c_getlastevent (I2C2));
}
Switch (i2c_getlastevent (I2C2))
{
Receive a matching address data
Case i2c_event_slave_transmitter_address_matched:
{
printf ("\ r \ n The i2c2 is ready \ r \ n");
I2c_generatestop (I2C2, DISABLE);
Break
}
Case i2c_event_slave_byte_transmitting://Send data
{
printf ("\ r \ n \ i2c2 transmits is transmitting \ r \ n");
I2c_senddata (I2C2, 0xb6 + rx_counter);
Break

}

Send data, send it, or lock it up, but Master didn't get it.
Case i2c_event_slave_byte_transmitted:
{

printf ("\ r \ n The i2c2 transmits one byte \ r \ n");

I2c_senddata (I2C2, 0xb6 + (rx_counter++));
Break
}
Case i2c_event_slave_stop_detected://Receive End condition
{
printf ("\ r \ n \ i2c2 is finish \ r \ n");
I2c_clearflag (I2c2,i2c_flag_stopf);
I2c_generatestop (I2C2, ENABLE);
Break
}
Default: {break;}
}
}


/*----------------------------------------------------------------------------------------------------
Name: I²c Test 24C02 Test
Written by: Mingzhang.zhao
Content: Test STM32F103VCT6 hardware i²c for interrupt and transmit data
Precautions:
1.USART1:PA9 is TX, PA10 is RX
I2c1:pb6 is SCL, PB7 is SDA
I2C2:PB10 is SCL, PB11 is SDA
----------------------------------------------------------------------------------------------------*/
#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);
void Delay (__io uint32_t t);
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)
{
Delay (1000);
I2c_generatestart (i2c1,enable); I2C1 Loop reading data
}
}


Initialization and configuration related
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;
Initialize i2c1gpio_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);
Initialize I2C2
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);
Initialize USART1
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)
{
/* Define enum type variable Hsestartupstatus */
ErrorStatus Hsestartupstatus;
/* Reset system Clock Settings */
Rcc_deinit ();
/* Open hse*/
Rcc_hseconfig (rcc_hse_on);
/* Wait for HSE to start vibrating and stabilize */
Hsestartupstatus = Rcc_waitforhsestartup ();
/* To determine if the HSE is successful, then enter if () inside * *
if (Hsestartupstatus = = SUCCESS)
{
/* Select HCLK (AHB) clock source for SYSCLK 1 */
Rcc_hclkconfig (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 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_apb
2periph_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_apb1pe
Riph_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_lastbit = 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);
}


void Delay (__io uint32_t t)
{
while (t--);
}
#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




refer:http://blog.csdn.net/g_salamander/article/details/8016698

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.