HT32_EXTI模拟I2C从机

lxbdebk / 2023-09-02 / 原文

随手记,实测可在100KHz下运行,参考这篇博主:

https://blog.csdn.net/goodrenze/article/details/124566706

以下四个语句请忽略

1 DIR_SCL_OUT

2 DIR_SDA_OUT

3 DIR_SCL_IN

4 DIR_SDA_IN 

.h文件

 1 #define    I2C_Master_Write                            (0)
 2 #define    I2C_Master_Read                             (1)
 3 #define    I2C_Slaver_SDA_SendH                        {BRIDGE_I2C_GPIO_PORT->DIRCR |= BRIDGE_I2C_SDA_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->SRR = BRIDGE_I2C_SDA_GPIO_PIN;}
 4 #define    I2C_Slaver_SCL_SendH                        {BRIDGE_I2C_GPIO_PORT->DIRCR |= BRIDGE_I2C_SCL_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->SRR = BRIDGE_I2C_SCL_GPIO_PIN;}
 5 #define    I2C_Slaver_SDA_SendL                        {BRIDGE_I2C_GPIO_PORT->DIRCR |= BRIDGE_I2C_SDA_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->RR  = BRIDGE_I2C_SDA_GPIO_PIN;}
 6 #define    I2C_Slaver_SCL_SendL                        {BRIDGE_I2C_GPIO_PORT->DIRCR |= BRIDGE_I2C_SCL_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->RR  = BRIDGE_I2C_SCL_GPIO_PIN;}    
 7 #define    I2C_Slaver_SDA_Receive                     {BRIDGE_I2C_GPIO_PORT->DIRCR &= ~BRIDGE_I2C_SDA_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->INER |= BRIDGE_I2C_SDA_GPIO_PIN;}
 8 #define    I2C_Slaver_SCL_Receive                     {BRIDGE_I2C_GPIO_PORT->DIRCR &= ~BRIDGE_I2C_SCL_GPIO_PIN; BRIDGE_I2C_GPIO_PORT->INER |= BRIDGE_I2C_SCL_GPIO_PIN;}
 9 #define    I2C_Slaver_SDA_Status                       ((BRIDGE_I2C_GPIO_PORT->DINR & BRIDGE_I2C_SDA_GPIO_PIN) > 0 ? 1 : 0)
10 #define    I2C_Slaver_SCL_Status                       ( BRIDGE_I2C_GPIO_PORT->DINR & BRIDGE_I2C_SCL_GPIO_PIN)
11 #define    I2C_Slaver_SendNACK                         {I2C_Slaver_SDA_SendH;}
12 #define    I2C_Slaver_SendACK                          {I2C_Slaver_SDA_SendL;}
13 
14 #define    I2C_Clock_Stretching_EN                     {DIR_SCL_OUT; I2C_Slaver_SCL_SendL;}                      // I2C Clock Stretching for slaver change level shift
15 #define    I2C_Clock_Stretching_DIS                    {DIR_SCL_IN;  I2C_Slaver_SCL_Receive;}                    // I2C Clock Stretching for slaver change level shift
16 
17 // I2C Slaver State enum
18 typedef enum{
19     STA_STOP = 0,                                      // STOP/IDLE
20     STA_START,                                         // START/BUSY
21     STA_ADDR,                                          // Master send address
22     STA_DATA,                                          // Transmit data between Master and Slaver
23     STA_ACK,
24     STA_NACK,
25     STA_ERROR
26 }SlaverStatus;                                         // @lxb20230829
27 
28 // I2C Master Send ACK enum
29 typedef enum {
30     I2C_Master_Send_ACK = 0, 
31     I2C_Master_Send_NACK = !I2C_Master_Send_ACK
32 }AckStatus;
33 
34 // I2C Slaver Address enum
35 typedef enum {
36     I2C_Addr_Mismatch = 0,
37     I2C_Addr_Match = !I2C_Addr_Mismatch 
38 }AddrStatus;
39 
40 // I2C Slaver edge struct
41 typedef struct{
42     struct{
43         vu8 bPositiveEdge_num;
44         vu8 bNegativeEdge_num;
45     }SCL;
46     
47     AddrStatus gGetAddr;                               // 0: Address mismatch                        1: Address match                  
48     AckStatus gGetAck;                                 // 0: Receive ACK                             1: Receive NACK
49     bool gACKofDATA;                                   // 0: ACK of address                          1: ACK of data
50     u8 gGetRW;                                         // 0: Master write(Slaver read)   1: Master read(Slaver write)
51     
52     SlaverStatus bState;
53     u8 bStartMs;                                       // Communication establishment time, starting from the start signal
54     u8 bAddr_SW;
55 }Bridge_I2C_Slaver_Typedef;                            // @lxb20230717
56 
57 
58 extern Bridge_I2C_Slaver_Typedef I2C_Slaver;

.c EXTI配置文件

 1 /*************************************************************************************************************
 2   * @brief  Configure the EXTI.
 3   * @retval None
 4   * @remark PC13 -> SDA
         PC12 -> SCL
 5   ***********************************************************************************************************/
 6 void EXTI_Config(void)
 7 {
 8   {
 9     CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
10     CKCUClock.Bit.PC   = 1;
11     CKCUClock.Bit.EXTI = 1;
12     CKCU_PeripClockConfig(CKCUClock, ENABLE);
13   }
14   GPIO_DirectionConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SDA_GPIO_PIN, GPIO_DIR_IN);
15   GPIO_DirectionConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SCL_GPIO_PIN, GPIO_DIR_IN);
16   GPIO_InputConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SDA_GPIO_PIN, ENABLE);    
17   GPIO_InputConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SCL_GPIO_PIN, ENABLE);
18   GPIO_PullResistorConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SDA_GPIO_PIN, GPIO_PR_DISABLE);
19   GPIO_PullResistorConfig(BRIDGE_I2C_GPIO_PORT, BRIDGE_I2C_SCL_GPIO_PIN, GPIO_PR_DISABLE);
20   AFIO_EXTISourceConfig(AFIO_EXTI_CH_13, AFIO_ESS_PC);                                                        // EXTI channel -> PC13
21   AFIO_EXTISourceConfig(AFIO_EXTI_CH_12, AFIO_ESS_PC);                                                        // EXTI channel -> PC12
22     
23   EXTI_InitStructure.EXTI_Channel = BRIDGE_EXTI_CHANNEL_SDA;
24   EXTI_InitStructure.EXTI_Debounce = EXTI_DEBOUNCE_DISABLE;
25   EXTI_InitStructure.EXTI_DebounceCnt = 0;
26   EXTI_InitStructure.EXTI_IntType = EXTI_BOTH_EDGE;
27   EXTI_Init(&EXTI_InitStructure);
28     
29   EXTI_InitStructure.EXTI_Channel = BRIDGE_EXTI_CHANNEL_SCL;
30   EXTI_InitStructure.EXTI_Debounce = EXTI_DEBOUNCE_DISABLE;
31   EXTI_InitStructure.EXTI_DebounceCnt = 0;
32   EXTI_InitStructure.EXTI_IntType = EXTI_BOTH_EDGE;
33   EXTI_Init(&EXTI_InitStructure);
34     
35   EXTI_IntConfig(BRIDGE_EXTI_CHANNEL_SDA, ENABLE);
36   EXTI_IntConfig(BRIDGE_EXTI_CHANNEL_SCL, ENABLE);
37   NVIC_EnableIRQ(BRIDGE_EXTI_IRQn);
38 }

.c EXTI中断函数文件

  1 /*********************************************************************************************************//**
  2  * @brief  This function handles EXTI 4~15 interrupt.
  3  * @retval None
  4  * @remark Bridge I2C slaver: Write data & Read data 
  5  ************************************************************************************************************/
  6 void EXTI4_15_IRQHandler(void)
  7 {
  8   /******************************************* SDA *******************************************/
  9   if ((HT_EXTI->EDGEFLGR & (1UL << BRIDGE_EXTI_CHANNEL_SDA)))                                                                                 /*< EXTI_GetEdgeFlag() >*/
 10   {
 11     /*---------------------------*/
 12     /* SDA Negative edge: START  */
 13     /*---------------------------*/
 14     if (GetBit_BB((u32)&HT_EXTI->EDGESR, BRIDGE_EXTI_CHANNEL_SDA) ^ EXTI_EDGE_NEGATIVE)                            /*< EXTI_GetEdgeStatus() >*/
 15     {
 16        if (I2C_Slaver_SCL_Status)                                                                                                                                      /*< if SCL high level >*/
 17            I2C_Slaver.bState = STA_START;
 18     }
 19     /*-------------------------*/
 20     /* SDA Positive edge: STOP */
 21     /*-------------------------*/        
 22     //else if (GetBit_BB((u32)&HT_EXTI->EDGESR, BRIDGE_EXTI_CHANNEL_SDA) ^ EXTI_EDGE_POSITIVE)                /*< EXTI_GetEdgeStatus() >*/
 23     else
 24     {
 25       if (I2C_Slaver_SCL_Status)                                                                                                                                      /*< if SCL high level >*/
 26       {
 27          I2C_Slaver.bState         = STA_STOP;
 28          I2C_Slaver.gGetAddr     = I2C_Addr_Mismatch;                                                                                                        
 29          I2C_Slaver.gGetRW         = I2C_Master_Write;                                                                                                    
 30          I2C_Slaver.gGetAck        = I2C_Master_Send_NACK;
 31          I2C_Slaver.gACKofDATA = FALSE;        
 32          I2C_Slaver.SCL.bPositiveEdge_num = 0;
 33       }
 34     }
 35   }
 36     
 37   /******************************************* SCL *******************************************/
 38   if ((HT_EXTI->EDGEFLGR & (1UL << BRIDGE_EXTI_CHANNEL_SCL)))                                                                                /*< EXTI_GetEdgeFlag() >*/
 39   {
 40     /*----------------------------------------------------*/
 41     /* SCL Negative edge: SDA change level to Update data */
 42     /*----------------------------------------------------*/
 43     if (GetBit_BB((u32)&HT_EXTI->EDGESR, BRIDGE_EXTI_CHANNEL_SCL) ^ EXTI_EDGE_NEGATIVE)                         /*< EXTI_GetEdgeStatus() >*/
 44     {
 45        switch (I2C_Slaver.bState)
 46        {
 47           // SCL Negative edge when I2C start or restart
 48           case STA_START: 
 49               {
 50                   RingBuffer_Init(&I2CRx_Ring, I2CRx_Ring.pMemory);
 51                   I2C_Slaver.bState = STA_ADDR;        
 52                   break;
 53               }
 54           // SCL Negative edge when master send address
 55           case STA_ADDR:
 56               {
 57                  if (I2C_Slaver.SCL.bPositiveEdge_num == 8)                                                                                            /*< SCL Positive Edge num 8 >*/
 58                  {
 59                     DIR_SDA_OUT;
 60                     if (I2C_Slaver.gGetAddr == I2C_Addr_Match)                                                                                        /*< Address match? >*/ 
 61                     {
 62                        I2C_Slaver_SendACK;                                                                                                                                    // Y
 63                        I2C_Slaver.bState = STA_ACK;
 64                     }
 65                     else
 66                     {
 67                        I2C_Slaver_SendNACK;                                                                                                                                // N
 68                        I2C_Slaver.bState = STA_STOP;
 69                      }
 70                  }
 71                  break;
 72               }
 73               // SCL Negative edge when I2C transmit data
 74               case STA_DATA: 
 75                   {
 76                      if (I2C_Slaver.SCL.bPositiveEdge_num == 8)                                                                                            /*< SCL Positive Edge num 8 >*/
 77                      {
 78                         if (I2C_Slaver.gGetRW == I2C_Master_Write)                                                                                        /*< if Master writer -> Slaver send ACK >*/ 
 79                         {
 80                             DIR_SDA_OUT;
 81                             I2C_Slaver_SendACK;
 82                             I2C_Slaver.gACKofDATA = TRUE;                                
 83                         }
 84                         else                                                                                                                                                                     /*< if Master read -> Slaver receive ACK >*/
 85                         {
 86                             DIR_SDA_IN;    
 87                             I2C_Slaver_SDA_Receive;                                
 88                             if (I2CTx_Ring.Head != I2CTx_Ring.Tail)                                                                                            // And ready to send the next byte
 89                             {
 90                                 I2CTx_Ring.Head++;                                                                                                                                
 91                                 I2CTx_Ring.Length--;
 92                             }
 93                          }
 94                          I2C_Slaver.bState = STA_ACK;
 95                     }
 96                     else if (I2C_Slaver.SCL.bPositiveEdge_num < 8)                                                                                    /*< SCL Positive Edge num 1~7 >*/
 97                     {
 98                         if (I2C_Slaver.gGetRW == I2C_Master_Read)                                                                                            /*< if Master read -> Slaver write data >*/
 99                         {
100                             DIR_SDA_OUT;
101                             if (I2CTx_Ring.pMemory[I2CTx_Ring.Head] & (0x80 >> I2C_Slaver.SCL.bPositiveEdge_num))
102                             {
103                                 I2C_Slaver_SDA_SendH;                                                                                                                         // Slaver change SDA level to H
104                             }
105                             else
106                             {
107                                 I2C_Slaver_SDA_SendL;                                                                                                                         // Slaver change SDA level to L
108                             }
109                         }
110                     }
111                     break;
112                 }
113                 // SCL Negative edge when I2C transmit ack
114                 case STA_ACK: 
115                     {
116                         I2C_Slaver.SCL.bPositiveEdge_num = 0;    
117                         if (I2C_Slaver.gGetRW == I2C_Master_Write)                                                                                            /*< if Master writer -> Slaver send ack >*/ 
118                         {
119                             DIR_SDA_IN;
120                             I2C_Slaver_SDA_Receive;    
121                             
122                             if (I2C_Slaver.gACKofDATA)
123                             {
124                                 I2CRx_Ring.Tail++;
125                                 I2CRx_Ring.Length++;
126                             }
127                         }
128                         else                                                                                                                                                                        /*< if Master read -> Slaver first change SDA level after send ACK >*/ 
129                         {
130                             DIR_SDA_OUT;
131                             if (I2CTx_Ring.pMemory[I2CTx_Ring.Head] & 0x80)
132                             {
133                                 I2C_Slaver_SDA_SendH;                                                                                                                             // Slaver change SDA level to H
134                             }
135                             else
136                             {
137                                 I2C_Slaver_SDA_SendL;                                                                                                                             // Slaver change SDA level to L
138                             }
139                         }
140                         I2C_Slaver.bState = STA_DATA;
141                         break;
142                     }
143                 // SCL Negative edge when I2C transmit nack
144                 case STA_NACK: 
145                     {
146                         I2C_Slaver.SCL.bPositiveEdge_num = 0;    
147                         DIR_SDA_IN;
148                         I2C_Slaver_SDA_Receive;
149                         break;
150                     }    
151                 default : break;
152             }
153         }
154     /*-------------------*/
155     /* SCL Positive edge */
156     /*-------------------*/    
157         //else if (GetBit_BB((u32)&HT_EXTI->EDGESR, BRIDGE_EXTI_CHANNEL_SCL) ^ EXTI_EDGE_POSITIVE)                 /*< EXTI_GetEdgeStatus() >*/
158         else
159         {
160             switch (I2C_Slaver.bState)
161             {
162                 // SCL Negative edge when master send address
163                 case STA_ADDR:    
164                     {
165                         I2C_Slaver.SCL.bPositiveEdge_num++;
166                         if (I2C_Slaver.SCL.bPositiveEdge_num <= 8)                                                                                        /*< if Master write -> Slaver read byte >*/
167                         {
168                             I2CRx_Ring.pMemory[0] = (I2CRx_Ring.pMemory[0] << 1) | I2C_Slaver_SDA_Status ;            // Slaver sampling bit (read byte)
169                             if ((I2CRx_Ring.pMemory[0] >> 1) == I2C_Slaver.bAddr_SW)
170                             {
171                                 I2C_Slaver.gGetAddr = I2C_Addr_Match;                                                                                            // Address match
172                                 I2C_Slaver.gGetRW = I2CRx_Ring.pMemory[0] & 0x01;                                                                    // Master read or write
173                             }
174                         }
175                         break;
176                     }
177                 // SCL Positive edge when I2C Master write data
178                 case STA_DATA:
179                     {
180                         I2C_Slaver.SCL.bPositiveEdge_num++;                                                                                                            // SCL Negative Edge num ++ in "STA_DATA"
181                         if ((I2C_Slaver.gGetRW == I2C_Master_Write) && (I2C_Slaver.SCL.bPositiveEdge_num <= 8))    /*< if Master write -> Slaver read byte >*/
182                         {
183                             I2CRx_Ring.pMemory[I2CRx_Ring.Tail] = (I2CRx_Ring.pMemory[I2CRx_Ring.Tail] << 1) | I2C_Slaver_SDA_Status ;    // Slaver sampling bit (read byte)
184                         }
185                         break;
186                     }        
187                 // SCL Positive edge when I2C Master write ACK
188                 case STA_ACK:
189                     {
190                         if (I2C_Slaver.gGetRW == I2C_Master_Read)
191                         {
192                             if (I2C_Slaver_SDA_Status)
193                                 I2C_Slaver.bState = STA_NACK;                                                                                                                // Slaver ready to receive RESTART or STOP
194                         }
195                         break;
196                     }                        
197                 default : break;
198             }
199         }
200     }
201     
202     /************************** Clear edge flag together at the end **************************/
203     HT_EXTI->EDGEFLGR = HT_EXTI->EDGESR = 1 << BRIDGE_EXTI_CHANNEL_SDA;                                                                // EXTI_ClearEdgeFlag()
204     HT_EXTI->EDGEFLGR = HT_EXTI->EDGESR = 1 << BRIDGE_EXTI_CHANNEL_SCL;                                                                // EXTI_ClearEdgeFlag()
205 }