HT32_EXTI模拟I2C从机

发布时间 2023-09-02 16:13:17作者: gejiji

随手记,实测可在100KHz下运行

  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 }