Simulate I2C interface code under STM32F103

Publisher:数字之舞Latest update time:2018-05-20 Source: eefocusKeywords:STM32F103 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Although hardware I2C is efficient, I always encounter various problems when debugging. I don’t have much time to mess around with it due to the rush of the project, so I use simulated I2C to complete it. Although the efficiency is not very good, it is simple and fast...

Without further ado, here is a fully annotated version of the simulated I2C code, which is applicable to the STM32 series. For other microcontrollers, you need to modify the definitions of SCL and SDA and modify the delay function.

  1. #include "stm32f10x.h"  

  2.   

  3. #define HIGH 1  

  4. #define LOW 0  

  5.   

  6. #define TRUE 1  

  7. #define FALSE  

  8.   

  9. /* Here we use the STM32F103RC chip, using PB6 and PB7 as SCL and SDA respectively.  

  10. Other chips use appropriate GPIO ports according to needs */  

  11. #define SDA_IN()  {GPIOB->CRL& = 0X0FFFFFFF; GPIOB->CRL |= 4<<28;}  

  12. #define SDA_OUT() {GPIOB->CRL& = 0X0FFFFFFF; GPIOB->CRL |= 3<<28;}  

  13. #define IIC_SCL    PBout(6) //SCL  

  14. #define IIC_SDA PBout(7) //SDA      

  15. #define READ_SDA PBin(7) // Input SDA  

  16.   

  17. void delay_us(u16 time)  

  18. {      

  19.    u16 i = 0;    

  20.    while(time--)  

  21.    {  

  22.       i = 10; //A random value, meaningless, just consuming CPU time, the compiler may be optimized    

  23.       while(i--);      

  24.    }  

  25. }  

  26.   

  27. /* Initialize I2C */  

  28. void IIC_Init(void)  

  29. {  

  30.     GPIO_InitTypeDef GPIO_Init_Structure;  

  31.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  

  32.     GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;  

  33.     GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_Out_PP;  

  34.     GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;  

  35.     GPIO_Init(GPIOB,&GPIO_Init_Structure);  

  36.     GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);  

  37. }  

  38.   

  39. /* Generate I2C start signal */  

  40. void IIC_Start(void)  

  41. {  

  42.     /* Set the SDA line to output */  

  43.     SDA_OUT();       

  44.       

  45.     /* Before starting to transmit data, pull both SDA and SCL high */  

  46.     IIC_SDA = HIGH;         

  47.     IIC_SCL = HIGH;  

  48.       

  49.     delay_us(5);  

  50.       

  51.     /* According to the I2C bus definition: When SCL is high, the data jumps from high to low to indicate the start signal */  

  52.     IIC_SDA = LOW;  

  53.     delay_us(5);  

  54.       

  55.     /*  

  56.     When SCL is low, no data is transmitted and it is not used as a start or end condition.  

  57.     So we can start sending data without causing a start or end signal  

  58.     This is called clamping the I2C bus. 

  59.     */  

  60.     IIC_SCL = LOW;  

  61. }  

  62.   

  63. /* Generate I2C stop signal */  

  64. void IIC_Stop(void)  

  65. {  

  66.     SDA_OUT(); //sda line output  

  67.       

  68.     /*  

  69.     First pull SCL low so that SDA can be switched to a low state without causing repeated start signals.  

  70.     Remember the previous comment on I2C Start? When SCL is high, SDA changes from high to low. 

  71.     */  

  72.     IIC_SCL = LOW;  

  73.       

  74.     /*  

  75.         SCL has been pulled low before, so here we can pull SDA low without restraint.  

  76.         Prepare for the end signal 

  77.     */  

  78.     IIC_SDA = LOW;  

  79.       

  80.     delay_us(5);  

  81.       

  82.     /* Okay, let's start generating the end signal: First, we need to pull SCL high (why? Because the I2C bus specifies 

  83.     Only when SCL is high is it the effective time to transmit data or generate start/end signals) */  

  84.     IIC_SCL = HIGH;   

  85.       

  86.     /* Okay, we have already pulled SDA low, so here we just need to set SDA high to complete it */  

  87.     IIC_SDA = HIGH;  

  88.     delay_us(5);                                  

  89. }  

  90.   

  91. /* 

  92. Meaning of the response signal: 

  93. The Master needs to wait for the Slave's ACK after sending each 8 bits of data. 

  94. That is, at the 9th clock, if the slave IC sends an ACK, then SDA will be pulled low. 

  95. If there is no ACK, SDA will be set high, which will cause the Master to issue a Restart or Stop process 

  96. */  

  97. /*  

  98.     Waiting for the response signal to arrive 

  99. */  

  100. u8 IIC_Wait_Ack(void)  

  101. {  

  102.     u8 ucErrTime = 0;   

  103.     IIC_SDA = HIGH;  

  104.     delay_us(5);  

  105.       

  106.     /* Set SDA to input mode, so as to read the ACK on SDA */  

  107.     SDA_IN();        

  108.       

  109.     /* Set SCL high to perform a read operation */  

  110.     IIC_SCL = HIGH;  

  111.     delay_us(5);      

  112.       

  113.     while(READ_SDA)  

  114.     {  

  115.         ucErrTime++;  

  116.         if(ucErrTime > 250)  

  117.         {//No ACK received from IC within the specified time, timeout processing  

  118.             return FALSE;  

  119.         }  

  120.     }  

  121.       

  122.     /*  

  123.     OK, this means there is no timeout and SDA is read as low, indicating that ACK confirmation is received  

  124.     Then you can go home and set SCL to low level (why? Because effective operations are all in 

  125.     Only when SCL is high) 

  126.     */  

  127.     IIC_SCL = LOW;  

  128.       

  129.     return TRUE;    

  130. }  

  131.   

  132. /* 

  133.  Send ACK confirmation operation 

  134.  The purpose of issuing this operation is to let the slave IC know that we have received the data. 

  135.  In this way, the IC will not perform the Restart or Stop process. 

  136. */  

  137. void IIC_Ack(void)  

  138. {  

  139.     /* The first step is to pull SCL low first to avoid SDA changes affecting I2C */  

  140.     IIC_SCL = LOW;  

  141.       

  142.     /* Then we set SDA to output mode and prepare to output data */  

  143.     SDA_OUT();  

  144.       

  145.     /* Pull SDA low, so that the confirmation signal is put on the bus, only the clock signal is missing */  

  146.     IIC_SDA = LOW;  

  147.       

  148.     delay_us(5);  

  149.       

  150.     /* Pull SCL high to generate the necessary valid operation clock signal */  

  151.     IIC_SCL = HIGH;  

  152.       

  153.     delay_us(5);  

  154.       

  155.     /*  

  156.     There has been a delay before, and the clock is almost up, so the ACK signal ends 

  157.     You can't keep occupying the bus all the time */  

  158.     IIC_SCL = LOW;  

  159. }  

  160.   

  161. /* 

  162. For NACK, the I2C bus is defined as follows: 

  163. When the SDA line remains high during the 9th clock pulse, it is defined as NACK. 

  164. The master either generates a Stop condition to abandon the transmission or repeats the Start condition to 

  165. Initiate a new beginning 

  166. */  

  167. void IIC_NAck(void)  

  168. {  

  169.     IIC_SCL = LOW;  

  170.     SDA_OUT();  

  171.       

  172.     /* According to the definition, pull SDA high as the definition of NACK */  

  173.     IIC_SDA = HIGH;  

  174.     delay_us(5);  

  175.       

  176.     /* Set to high level, send NACK signal */  

  177.     IIC_SCL = HIGH;  

  178.     delay_us(5);  

  179.       

  180.     /* Pull SCL low, sending completed */  

  181.     IIC_SCL = LOW;  

  182. }  

  183.   

  184. void IIC_Send_Byte(u8 txd)  

  185. {                          

  186.     u8 t;    

  187.     /* Now that data transmission has started, switch the SDA port to output mode first */      

  188.     SDA_OUT();     

  189.   

  190.     /* Pull the clock signal low, prepare the data and then pull it high for transmission */      

  191.     IIC_SCL = LOW;  

  192.     for(t = 0; t < 8; t++)  

  193.     {       

  194.         /* I2C data is transmitted in big-endian format, i.e. the high bit is transmitted first */  

  195.         if((txd&0x80) >> 7)  

  196.             IIC_SDA = HIGH;  

  197.         else  

  198.             IIC_SDA = LOW;  

  199.           

  200.         txd <<= 1;   

  201.         /* It is necessary to make a delay */          

  202.         delay_us(5);     

  203.           

  204.         /* Pull SCL high to transmit data */  

  205.         IIC_SCL = HIGH;  

  206.           

  207.         delay_us(5);  

  208.           

  209.         /* Pull SCL low, transmission completed */  

  210.         IIC_SCL = LOW;    

  211.           

  212.         delay_us(5);  

  213.     }      

  214. }   

  215.   

  216. u8 IIC_Read_Byte(void)  

  217. {  

  218.     unsigned char i, receive = 0;  

  219.       

  220.     /* Switch the SDA port to input mode, ready to read data */  

  221.     SDA_IN();  

  222.       

  223.     for(i = 0; i < 8; i++ )  

  224.     {  

  225.         /* Pull SCL low */  

  226.         IIC_SCL = LOW;   

  227.         delay_us(5);  

  228.           

  229.         /* Pull SCL high again to generate a valid clock signal */  

  230.         IIC_SCL = HIGH;  

  231.           

  232.         /* Read data on the bus */  

  233.         receive = (receive << 1) | READ_SDA;  

  234.           

  235.         delay_us(5);   

  236.     }  

  237.       

  238.     return receive;  

  239. }  


Keywords:STM32F103 Reference address:Simulate I2C interface code under STM32F103

Previous article:Detailed explanation of STM32 startup assembler
Next article:GPIO port simulates I2C

Recommended ReadingLatest update time:2024-11-16 14:49

STM32F103 series practical DMA controller
Introduction to DMA Direct Memory Access (DMA) is used to provide high-speed data transfers between peripherals and memory or between memory and memory. Data can be moved quickly through DMA without CPU intervention, which saves CPU resources for other operations. Flexible 12-way general-purpose DMA (7 channels on D
[Microcontroller]
STM32F103 series practical DMA controller
STM32F103 series USB issues
1. USB and CAN share 512B of RAM, but the RAm address is 0x40006000-0x40006400, which is clearly 1KB, so why is it still 512B? 2. What should I do if I write to the RAM while the PC is reading data from it? I feel like the library doesn't handle this kind of operation. 3. For the buffer, I don't understand w
[Microcontroller]
STM32F103 PB3 PB4 is set to normal GPIO configuration
Recently, due to the task, I made a board with STM32F103C8T6. I used to use JLINK to download programs to the chip , and never used the STM32 JTAG download function. The JTAG function includes PB3 and PB4. This time, the board I made happened to use the PB3 pin as a normal GPIO port. I debugged it for a day without kn
[Microcontroller]
The first program of STM32F103RCT6 - Marquee program
The following is a brief introduction to the main aspects that need to be configured in the Marquee program: 1. Configure GPIO mode The CRL and CRH registers are used to configure the mode and rate of the STM32 IO port;  GPIO has 8 working modes:  1. Input floating  2. Input pull-up  3. Input drop-down  4. Analog
[Microcontroller]
STM32F103ZET6 — Port Remap
When I was about to play with the advanced timer TIM1 / TIM8 on STM32F103ZET6, I suddenly found some port multiplexing problems: The pins of TIM1 are as follows: The pins of USART2 are as follows: The default value of the remap register AFIO is 0x0000 0000 This means that the above-mentioned PA9 and PA10 are used
[Microcontroller]
Analysis of computer mouse control system solution based on STM32F103RCT6
1 How does a computer mouse work? Six groups of infrared sensors are installed around the computer mouse, which sense the left, left front, front, right front, and right respectively. The transmitting end emits infrared rays of a certain frequency, and the receiving end determines whether there are obstacles th
[Microcontroller]
Analysis of computer mouse control system solution based on STM32F103RCT6
The configuration of STM32F103ZE GPIO port takes the running light as an example
Setup steps: 1. Enable peripheral clocks such as PA, PB, PE. 2. Set to the desired state. Here is the push-pull output 50Khz rate 3. Set the output state, whether it is high level or low level. You can set it using ODR, BSRR, or BSR. code show as below: #include “stm32f10x.h” extern void Stm32_Clock_Init(u8 PLL); vo
[Microcontroller]
Simulate I2C interface code under STM32F103
Although hardware I2C is efficient, I always encounter various problems when debugging. I don’t have much time to mess around with it due to the rush of the project, so I use simulated I2C to complete it. Although the efficiency is not very good, it is simple and fast... Without further ado, here is a fully annotated
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号