test
This commit is contained in:
		| @@ -18,7 +18,11 @@ set(TARGET_C_SRC | |||||||
|         ${CMAKE_SOURCE_DIR}/src/main.c |         ${CMAKE_SOURCE_DIR}/src/main.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/gd32e23x_it.c |         ${CMAKE_SOURCE_DIR}/src/gd32e23x_it.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/systick.c |         ${CMAKE_SOURCE_DIR}/src/systick.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/peripheral.c |         ${CMAKE_SOURCE_DIR}/src/rs485.c | ||||||
|  |         ${CMAKE_SOURCE_DIR}/src/led.c | ||||||
|  |         ${CMAKE_SOURCE_DIR}/src/i2c.c | ||||||
|  |         ${CMAKE_SOURCE_DIR}/src/soft_i2c.c | ||||||
|  |         ${CMAKE_SOURCE_DIR}/src/fwdgt.c | ||||||
| ) | ) | ||||||
|  |  | ||||||
| add_executable(gd32e23x_template ${TARGET_C_SRC}) | add_executable(gd32e23x_template ${TARGET_C_SRC}) | ||||||
|   | |||||||
| @@ -15,7 +15,6 @@ set(TARGET_C_SRC | |||||||
|         ${CMAKE_SOURCE_DIR}/src/main.c |         ${CMAKE_SOURCE_DIR}/src/main.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/gd32e23x_it.c |         ${CMAKE_SOURCE_DIR}/src/gd32e23x_it.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/systick.c |         ${CMAKE_SOURCE_DIR}/src/systick.c | ||||||
|         ${CMAKE_SOURCE_DIR}/src/peripheral.c |  | ||||||
| ) | ) | ||||||
| ``` | ``` | ||||||
| ## 关于链接脚本 | ## 关于链接脚本 | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								inc/board_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								inc/board_config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-28. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef BOARD_CONFIG_H | ||||||
|  | #define BOARD_CONFIG_H | ||||||
|  |  | ||||||
|  | #define SOFTWARE_IIC | ||||||
|  |  | ||||||
|  | // #define DEBUG_VERBOES | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define RCU_GPIO_I2C         RCU_GPIOF | ||||||
|  | #define RCU_I2C              RCU_I2C0 | ||||||
|  | #define I2C_SCL_PORT         GPIOF | ||||||
|  | #define I2C_SCL_PIN          GPIO_PIN_1 | ||||||
|  | #define I2C_SDA_PORT         GPIOF | ||||||
|  | #define I2C_SDA_PIN          GPIO_PIN_0 | ||||||
|  | #define I2C_GPIO_AF          GPIO_AF_1 | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define RS485_RCU            RCU_USART0 | ||||||
|  | #define RS485_GPIO_RCU       RCU_GPIOA | ||||||
|  | #define RS485_GPIO_PORT      GPIOA | ||||||
|  | #define RS485_TX_PIN         GPIO_PIN_2 | ||||||
|  | #define RS485_RX_PIN         GPIO_PIN_3 | ||||||
|  | #define RS485_PHY            USART0 | ||||||
|  | #define RS485_BAUDRATE       115200U | ||||||
|  | #define RS485_EN_PIN         GPIO_PIN_1 | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define LED_PORT             GPIOA | ||||||
|  | #define LED_PIN              GPIO_PIN_7 | ||||||
|  | #define LED_RCU              RCU_GPIOA | ||||||
|  | #define LED_BLINK_TIMER_RCU  RCU_TIMER16 | ||||||
|  | #define LED_BLINK_TIMER      TIMER16 | ||||||
|  | #define LED_BLINK_IRQ        TIMER16_IRQn | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #endif //BOARD_CONFIG_H | ||||||
							
								
								
									
										15
									
								
								inc/fwdgt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								inc/fwdgt.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | // | ||||||
|  | // Created by yelv1 on 24-12-29. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef FWDGT_H | ||||||
|  | #define FWDGT_H | ||||||
|  |  | ||||||
|  | #include "gd32e23x.h" | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | void watchdog_init(void); | ||||||
|  |  | ||||||
|  | void fwdgt_reset_mcu(void); | ||||||
|  |  | ||||||
|  | #endif //FWDGT_H | ||||||
							
								
								
									
										48
									
								
								inc/i2c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								inc/i2c.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef I2C_H | ||||||
|  | #define I2C_H | ||||||
|  |  | ||||||
|  | #include "gd32e23x_it.h" | ||||||
|  | #include "gd32e23x.h" | ||||||
|  | #include "systick.h" | ||||||
|  | #include "main.h" | ||||||
|  |  | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define I2C_SPEED       20000 | ||||||
|  |  | ||||||
|  | #define I2C_TIME_OUT    (uint16_t)(5000) | ||||||
|  | #define I2C_OK          1 | ||||||
|  | #define I2C_FAIL        0 | ||||||
|  | #define I2C_END         1 | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |     I2C_START = 0, | ||||||
|  |     I2C_SEND_ADDRESS, | ||||||
|  |     I2C_CLEAR_ADDRESS_FLAG, | ||||||
|  |     I2C_TRANSMIT_DATA, | ||||||
|  |     I2C_STOP | ||||||
|  | } i2c_process_enum; | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | void i2c_gpio_config(void); | ||||||
|  |  | ||||||
|  | void i2c_config(void); | ||||||
|  |  | ||||||
|  | void i2c_bus_reset(void); | ||||||
|  |  | ||||||
|  | void i2c_scan(void); | ||||||
|  |  | ||||||
|  | uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]); | ||||||
|  |  | ||||||
|  | uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data); | ||||||
|  |  | ||||||
|  | #endif //I2C_H | ||||||
							
								
								
									
										13
									
								
								inc/led.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								inc/led.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef LED_H | ||||||
|  | #define LED_H | ||||||
|  |  | ||||||
|  | #include "gd32e23x_it.h" | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | void led_config(void); | ||||||
|  |  | ||||||
|  | #endif //LED_H | ||||||
							
								
								
									
										16
									
								
								inc/main.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								inc/main.h
									
									
									
									
									
								
							| @@ -35,4 +35,20 @@ OF SUCH DAMAGE. | |||||||
| #ifndef MAIN_H | #ifndef MAIN_H | ||||||
| #define MAIN_H | #define MAIN_H | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "gd32e23x.h" | ||||||
|  | #include "systick.h" | ||||||
|  | #include "gd32e23x_libopt.h" | ||||||
|  | #include "rs485.h" | ||||||
|  | #include "led.h" | ||||||
|  | #include "fwdgt.h" | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | #ifdef SOFTWARE_IIC | ||||||
|  | #include "soft_i2c.h" | ||||||
|  | #else | ||||||
|  | #include "i2c.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif /* MAIN_H */ | #endif /* MAIN_H */ | ||||||
|   | |||||||
| @@ -1,11 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by yelv1 on 24-9-22. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef PERIPHERAL_H |  | ||||||
| #define PERIPHERAL_H |  | ||||||
|  |  | ||||||
| void usart_config(void); |  | ||||||
| void led_blink_config(void); |  | ||||||
|  |  | ||||||
| #endif //PERIPHERAL_H |  | ||||||
							
								
								
									
										22
									
								
								inc/rs485.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								inc/rs485.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-3. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef RS485_H | ||||||
|  | #define RS485_H | ||||||
|  |  | ||||||
|  | #include "gd32e23x_it.h" | ||||||
|  | #include "gd32e23x.h" | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define RX_BUFFER_SIZE            32 | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | void usart_config(void); | ||||||
|  |  | ||||||
|  | void rs485_config(void); | ||||||
|  |  | ||||||
|  | #endif //RS485_H | ||||||
							
								
								
									
										53
									
								
								inc/soft_i2c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								inc/soft_i2c.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-28. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef SOFT_I2C_H | ||||||
|  | #define SOFT_I2C_H | ||||||
|  |  | ||||||
|  | #include "gd32e23x_it.h" | ||||||
|  | #include "gd32e23x.h" | ||||||
|  | #include "systick.h" | ||||||
|  | #include "main.h" | ||||||
|  |  | ||||||
|  | #include "board_config.h" | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define I2C_SCL_HIGH()      gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN) | ||||||
|  | #define I2C_SCL_LOW()       gpio_bit_reset(I2C_SCL_PORT, I2C_SCL_PIN) | ||||||
|  | #define I2C_SDA_HIGH()      gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN) | ||||||
|  | #define I2C_SDA_LOW()       gpio_bit_reset(I2C_SDA_PORT, I2C_SDA_PIN) | ||||||
|  | #define I2C_SDA_READ()      gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN) | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | #define SOFT_I2C_OK          1 | ||||||
|  | #define SOFT_I2C_FAIL        0 | ||||||
|  | #define SOFT_I2C_END         1 | ||||||
|  |  | ||||||
|  | /******************************************************************************/ | ||||||
|  |  | ||||||
|  | void soft_i2c_delay(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_config(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_start(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_stop(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_send_ack(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_send_nack(void); | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_wait_ack(void); | ||||||
|  |  | ||||||
|  | void soft_i2c_send_byte(uint8_t data); | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_receive_byte(uint8_t ack); | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]); | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data); | ||||||
|  |  | ||||||
|  | #endif //SOFT_I2C_H | ||||||
| @@ -45,7 +45,7 @@ | |||||||
|  |  | ||||||
| /* select a system clock by uncommenting the following line */ | /* select a system clock by uncommenting the following line */ | ||||||
| //#define __SYSTEM_CLOCK_8M_HXTAL              (__HXTAL) | //#define __SYSTEM_CLOCK_8M_HXTAL              (__HXTAL) | ||||||
| //#define __SYSTEM_CLOCK_8M_IRC8M              (__IRC8M) | // #define __SYSTEM_CLOCK_8M_IRC8M              (__IRC8M) | ||||||
| // #define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000) | // #define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000) | ||||||
| #define __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2    (uint32_t)(72000000) | #define __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2    (uint32_t)(72000000) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								src/fwdgt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/fwdgt.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | // | ||||||
|  | // Created by yelv1 on 24-12-29. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "fwdgt.h" | ||||||
|  |  | ||||||
|  | void watchdog_init(void) { | ||||||
|  |     /* Enable the LSI clock */ | ||||||
|  |     rcu_osci_on(RCU_IRC40K); | ||||||
|  |     rcu_osci_stab_wait(RCU_IRC40K); | ||||||
|  |  | ||||||
|  |     /* Configure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz */ | ||||||
|  |     fwdgt_config(625, FWDGT_PSC_DIV64); // Set timeout to 1 seconds (625 / 0.625 KHz) | ||||||
|  |  | ||||||
|  |     /* Enable FWDGT */ | ||||||
|  |     fwdgt_enable(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void fwdgt_reset_mcu(void) { | ||||||
|  |     /* Enable the write access to the FWDGT_CTL register */ | ||||||
|  |     FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; | ||||||
|  |  | ||||||
|  |     /* Configure FWDGT to trigger a system reset */ | ||||||
|  |     fwdgt_config(50, FWDGT_PSC_DIV4); | ||||||
|  |  | ||||||
|  |     /* Reload the counter to trigger the reset */ | ||||||
|  |     fwdgt_counter_reload(); | ||||||
|  | } | ||||||
| @@ -35,6 +35,8 @@ OF SUCH DAMAGE. | |||||||
| #include "gd32e23x_it.h" | #include "gd32e23x_it.h" | ||||||
| #include "main.h" | #include "main.h" | ||||||
| #include "systick.h" | #include "systick.h" | ||||||
|  | #include "rs485.h" | ||||||
|  | #include "led.h" | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|     \brief      this function handles NMI exception |     \brief      this function handles NMI exception | ||||||
| @@ -42,10 +44,9 @@ OF SUCH DAMAGE. | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| void NMI_Handler(void) | void NMI_Handler(void) { | ||||||
| { |  | ||||||
|     /* if NMI exception occurs, go to infinite loop */ |     /* if NMI exception occurs, go to infinite loop */ | ||||||
|     while(1) { |     while (1) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -55,10 +56,9 @@ void NMI_Handler(void) | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| void HardFault_Handler(void) | void HardFault_Handler(void) { | ||||||
| { |  | ||||||
|     /* if Hard Fault exception occurs, go to infinite loop */ |     /* if Hard Fault exception occurs, go to infinite loop */ | ||||||
|     while(1) { |     while (1) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -68,10 +68,9 @@ void HardFault_Handler(void) | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| void SVC_Handler(void) | void SVC_Handler(void) { | ||||||
| { |  | ||||||
|     /* if SVC exception occurs, go to infinite loop */ |     /* if SVC exception occurs, go to infinite loop */ | ||||||
|     while(1) { |     while (1) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -81,10 +80,9 @@ void SVC_Handler(void) | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| void PendSV_Handler(void) | void PendSV_Handler(void) { | ||||||
| { |  | ||||||
|     /* if PendSV exception occurs, go to infinite loop */ |     /* if PendSV exception occurs, go to infinite loop */ | ||||||
|     while(1) { |     while (1) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -94,25 +92,25 @@ void PendSV_Handler(void) | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| void SysTick_Handler(void) | void SysTick_Handler(void) { | ||||||
| { |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void TIMER13_IRQHandler(void) | /** | ||||||
| { |   * @brief  This function handles TIMER5 interrupt request. | ||||||
|     if (timer_interrupt_flag_get(TIMER13, TIMER_INT_FLAG_UP) == SET) |   * @param[in]  none | ||||||
|     { |   * @param[out] none | ||||||
|         timer_interrupt_flag_clear(TIMER13, TIMER_INT_FLAG_UP); |   * @retval None | ||||||
|  |   */ | ||||||
|  | void TIMER16_IRQHandler(void) { | ||||||
|  |     if (timer_interrupt_flag_get(LED_BLINK_TIMER, TIMER_INT_FLAG_UP) == SET) { | ||||||
|  |         timer_interrupt_flag_clear(LED_BLINK_TIMER, TIMER_INT_FLAG_UP); | ||||||
|         static uint8_t led_status = 0; |         static uint8_t led_status = 0; | ||||||
|         if (led_status) |         if (led_status) { | ||||||
|         { |             gpio_bit_write(LED_PORT, LED_PIN, RESET); | ||||||
|             //! turn on led & reconfig timer13 period to 19000(1900ms) |             timer_autoreload_value_config(LED_BLINK_TIMER, 19200); | ||||||
|             gpio_bit_write(GPIOB, GPIO_PIN_1, RESET); |  | ||||||
|             timer_autoreload_value_config(TIMER13, 19200); |  | ||||||
|         } else { |         } else { | ||||||
|             //! turn off led & reconfig timer13 period to 1000(100ms) |             gpio_bit_write(LED_PORT, LED_PIN, SET); | ||||||
|             gpio_bit_write(GPIOB, GPIO_PIN_1, SET); |             timer_autoreload_value_config(LED_BLINK_TIMER, 800); | ||||||
|             timer_autoreload_value_config(TIMER13, 800); |  | ||||||
|         } |         } | ||||||
|         led_status = !led_status; |         led_status = !led_status; | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										491
									
								
								src/i2c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								src/i2c.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,491 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "i2c.h" | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      configure the GPIO ports | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void i2c_gpio_config(void) { | ||||||
|  |     /* enable IIC GPIO clock */ | ||||||
|  |     rcu_periph_clock_enable(RCU_GPIO_I2C); | ||||||
|  |  | ||||||
|  |     /* connect I2C_SCL_PIN to I2C_SCL */ | ||||||
|  |     gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN); | ||||||
|  |     /* connect I2C_SDA_PIN to I2C_SDA */ | ||||||
|  |     gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN); | ||||||
|  |     /* configure GPIO pins of I2C */ | ||||||
|  |     gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); | ||||||
|  |     gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      configure the I2CX interface | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void i2c_config(void) { | ||||||
|  |     /* configure I2C GPIO */ | ||||||
|  |     i2c_gpio_config(); | ||||||
|  |     /* enable I2C clock */ | ||||||
|  |     rcu_periph_clock_enable(RCU_I2C); | ||||||
|  |     /* configure I2C clock */ | ||||||
|  |     i2c_clock_config(I2C0, I2C_SPEED, I2C_DTCY_2); | ||||||
|  |     /* configure I2C address */ | ||||||
|  |     i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0xA0); | ||||||
|  |     /* enable I2CX */ | ||||||
|  |     i2c_enable(I2C0); | ||||||
|  |     /* enable acknowledge */ | ||||||
|  |     i2c_ack_config(I2C0, I2C_ACK_ENABLE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      reset I2C bus | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void i2c_bus_reset(void) { | ||||||
|  |     i2c_deinit(I2C0); | ||||||
|  |     /* configure SDA/SCL for GPIO */ | ||||||
|  |     GPIO_BC(I2C_SCL_PORT) |= I2C_SCL_PIN; | ||||||
|  |     GPIO_BC(I2C_SDA_PORT) |= I2C_SDA_PIN; | ||||||
|  |     gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     GPIO_BOP(I2C_SCL_PORT) |= I2C_SCL_PIN; | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     __NOP(); | ||||||
|  |     GPIO_BOP(I2C_SDA_PORT) |= I2C_SDA_PIN; | ||||||
|  |     /* connect I2C_SCL_PIN to I2C_SCL */ | ||||||
|  |     /* connect I2C_SDA_PIN to I2C_SDA */ | ||||||
|  |     gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); | ||||||
|  |     /* configure the I2CX interface */ | ||||||
|  |     i2c_config(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief 扫描I2C总线,查找连接的设备 | ||||||
|  |  * | ||||||
|  |  * 该函数会扫描I2C总线上的所有地址(1到126),并尝试与每个地址进行通信。 | ||||||
|  |  * 如果在某个地址上发现了设备,则会打印出该设备的地址。 | ||||||
|  |  * 最后会打印出找到的设备总数。 | ||||||
|  |  */ | ||||||
|  | void i2c_scan(void) { | ||||||
|  |     uint32_t timeout; | ||||||
|  |     uint8_t address; | ||||||
|  |     int found_devices = 0; | ||||||
|  |  | ||||||
|  |     printf("Scanning I2C bus...\r\n"); | ||||||
|  |  | ||||||
|  |     for (address = 1; address < 127; address++) { | ||||||
|  |         timeout = 0; | ||||||
|  |  | ||||||
|  |         // 生成起始条件 | ||||||
|  |         while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) | ||||||
|  |             timeout++; | ||||||
|  |         if (timeout >= I2C_TIME_OUT) { | ||||||
|  |             continue; // 超时,跳过该地址 | ||||||
|  |         } | ||||||
|  |         i2c_start_on_bus(I2C0); | ||||||
|  |         timeout = 0; | ||||||
|  |  | ||||||
|  |         // 等待起始条件发送完成 | ||||||
|  |         while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND) && (timeout < I2C_TIME_OUT)) | ||||||
|  |             timeout++; | ||||||
|  |         if (timeout >= I2C_TIME_OUT) { | ||||||
|  |             continue; // 超时,跳过该地址 | ||||||
|  |         } | ||||||
|  |         i2c_master_addressing(I2C0, (address << 1), I2C_TRANSMITTER); | ||||||
|  |         timeout = 0; | ||||||
|  |  | ||||||
|  |         // 等待地址发送完成 | ||||||
|  |         while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND) && (timeout < I2C_TIME_OUT)) | ||||||
|  |             timeout++; | ||||||
|  |         if (timeout < I2C_TIME_OUT) { | ||||||
|  |             i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); | ||||||
|  |             printf("Found device at 0x%02X\r\n", address); | ||||||
|  |             found_devices++; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 生成停止条件 | ||||||
|  |         i2c_stop_on_bus(I2C0); | ||||||
|  |  | ||||||
|  |         timeout = 0; | ||||||
|  |  | ||||||
|  |         while (i2c_flag_get(I2C0, I2C_FLAG_STPDET) && (timeout < I2C_TIME_OUT)) | ||||||
|  |             timeout++; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (found_devices == 0) { | ||||||
|  |         printf("No I2C devices found.\r\n"); | ||||||
|  |     } else { | ||||||
|  |         printf("Total %d I2C devices found.\r\n", found_devices); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      write 16 bits data to the specified register of the slave device | ||||||
|  |     \param[in]  slave_addr: slave device address | ||||||
|  |     \param[in]  reg_addr: register address | ||||||
|  |     \param[in]  data: data to be written | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     0: failed, 1: success | ||||||
|  | */ | ||||||
|  | uint8_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]) { | ||||||
|  |     uint8_t state = I2C_START; | ||||||
|  |     uint16_t timeout = 0; | ||||||
|  |     uint8_t i2c_timeout_flag = 0; | ||||||
|  |  | ||||||
|  |     /* enable acknowledge */ | ||||||
|  |     i2c_ack_config(I2C0, I2C_ACK_ENABLE); | ||||||
|  |     while (!(i2c_timeout_flag)) { | ||||||
|  |         switch (state) { | ||||||
|  |             case I2C_START: | ||||||
|  |                 /* i2c master sends start signal only when the bus is idle */ | ||||||
|  |                 while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     i2c_start_on_bus(I2C0); | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_SEND_ADDRESS; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c bus is busy in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_SEND_ADDRESS: | ||||||
|  |                 /* i2c master sends START signal successfully */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     i2c_master_addressing(I2C0, slave_addr, I2C_TRANSMITTER); | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_CLEAR_ADDRESS_FLAG; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends start signal timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_CLEAR_ADDRESS_FLAG: | ||||||
|  |                 /* address flag set means i2c slave sends ACK */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_TRANSMIT_DATA; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master clears address flag timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_TRANSMIT_DATA: | ||||||
|  |                 /* wait until the transmit data buffer is empty */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     /* send IIC register address */ | ||||||
|  |                     i2c_data_transmit(I2C0, reg_addr); | ||||||
|  |                     timeout = 0; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends data timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             /* wait until BTC bit is set */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     /* send register MSB value */ | ||||||
|  |                     i2c_data_transmit(I2C0, data[0]); | ||||||
|  |                     timeout = 0; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends MSB data timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             /* wait until BTC bit is set */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     /* send register LSB value */ | ||||||
|  |                     i2c_data_transmit(I2C0, data[1]); | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_STOP; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends LSB data timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             /* wait until BTC bit is set */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     state = I2C_STOP; | ||||||
|  |                     timeout = 0; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends data timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_STOP: | ||||||
|  |                 /* send a stop condition to I2C bus */ | ||||||
|  |                 i2c_stop_on_bus(I2C0); | ||||||
|  |             /* i2c master sends STOP signal successfully */ | ||||||
|  |                 while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_END; | ||||||
|  |                     i2c_timeout_flag = I2C_OK; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends stop signal timeout in WRITE BYTE!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 state = I2C_START; | ||||||
|  |                 i2c_timeout_flag = I2C_OK; | ||||||
|  |                 timeout = 0; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                 printf("i2c master sends start signal in WRITE BYTE.\n"); | ||||||
|  | #endif | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return I2C_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      read 16 bits data from the specified register of the slave device | ||||||
|  |     \param[in]  slave_addr: slave device address | ||||||
|  |     \param[in]  reg_addr: register address | ||||||
|  |     \param[out] data: data to be read | ||||||
|  |     \retval     0: failed, 1: success | ||||||
|  | */ | ||||||
|  | uint8_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) { | ||||||
|  |     uint8_t state = I2C_START; | ||||||
|  |     uint8_t read_cycle = 0; | ||||||
|  |     uint16_t timeout = 0; | ||||||
|  |     uint8_t i2c_timeout_flag = 0; | ||||||
|  |     uint8_t number_of_byte = 2; | ||||||
|  |  | ||||||
|  |     /* enable acknowledge */ | ||||||
|  |     i2c_ack_config(I2C0, I2C_ACK_ENABLE); | ||||||
|  |  | ||||||
|  |     while (!(i2c_timeout_flag)) { | ||||||
|  |         switch (state) { | ||||||
|  |             case I2C_START: | ||||||
|  |                 if (RESET == read_cycle) { | ||||||
|  |                     /* i2c master sends start signal only when the bus is idle */ | ||||||
|  |                     while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                         timeout++; | ||||||
|  |                     } | ||||||
|  |                     if (timeout < I2C_TIME_OUT) { | ||||||
|  |                         /* whether to send ACK or not for the next byte */ | ||||||
|  |                         i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT); | ||||||
|  |                     } else { | ||||||
|  |                         // i2c_bus_reset(); | ||||||
|  |                         timeout = 0; | ||||||
|  |                         state = I2C_START; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                         printf("i2c bus is busy in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             /* send the start signal */ | ||||||
|  |                 i2c_start_on_bus(I2C0); | ||||||
|  |                 timeout = 0; | ||||||
|  |                 state = I2C_SEND_ADDRESS; | ||||||
|  |                 break; | ||||||
|  |             case I2C_SEND_ADDRESS: | ||||||
|  |                 /* i2c master sends START signal successfully */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     if (RESET == read_cycle) { | ||||||
|  |                         i2c_master_addressing(I2C0, slave_addr, I2C_TRANSMITTER); | ||||||
|  |                         state = I2C_CLEAR_ADDRESS_FLAG; | ||||||
|  |                     } else { | ||||||
|  |                         i2c_master_addressing(I2C0, slave_addr, I2C_RECEIVER); | ||||||
|  |                         i2c_ack_config(I2C0, I2C_ACK_DISABLE); | ||||||
|  |                         state = I2C_CLEAR_ADDRESS_FLAG; | ||||||
|  |                     } | ||||||
|  |                     timeout = 0; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  |                     read_cycle = RESET; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends start signal timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_CLEAR_ADDRESS_FLAG: | ||||||
|  |                 /* address flag set means i2c slave sends ACK */ | ||||||
|  |                 while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); | ||||||
|  |                     if ((SET == read_cycle) && (1 == number_of_byte)) { | ||||||
|  |                         /* send a stop condition to I2C bus */ | ||||||
|  |                         i2c_stop_on_bus(I2C0); | ||||||
|  |                     } | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_TRANSMIT_DATA; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  |                     read_cycle = RESET; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master clears address flag timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_TRANSMIT_DATA: | ||||||
|  |                 if (RESET == read_cycle) { | ||||||
|  |                     /* wait until the transmit data buffer is empty */ | ||||||
|  |                     while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                         timeout++; | ||||||
|  |                     } | ||||||
|  |                     if (timeout < I2C_TIME_OUT) { | ||||||
|  |                         /* send the EEPROM's internal address to write to : only one byte address */ | ||||||
|  |                         i2c_data_transmit(I2C0, reg_addr); | ||||||
|  |                         timeout = 0; | ||||||
|  |                     } else { | ||||||
|  |                         timeout = 0; | ||||||
|  |                         state = I2C_START; | ||||||
|  |                         read_cycle = RESET; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                         printf("i2c master wait data buffer is empty timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                     } | ||||||
|  |                     /* wait until BTC bit is set */ | ||||||
|  |                     while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                         timeout++; | ||||||
|  |                     } | ||||||
|  |                     if (timeout < I2C_TIME_OUT) { | ||||||
|  |                         timeout = 0; | ||||||
|  |                         state = I2C_START; | ||||||
|  |                         read_cycle = SET; | ||||||
|  |                     } else { | ||||||
|  |                         timeout = 0; | ||||||
|  |                         state = I2C_START; | ||||||
|  |                         read_cycle = RESET; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                         printf("i2c master sends register address timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     while (number_of_byte) { | ||||||
|  |                         timeout++; | ||||||
|  |                         if (2 == number_of_byte) { | ||||||
|  |                             /* wait until BTC bit is set */ | ||||||
|  |                             while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)); | ||||||
|  |                             /* send a stop condition to I2C bus */ | ||||||
|  |                             i2c_stop_on_bus(I2C0); | ||||||
|  |                         } | ||||||
|  |                         /* wait until RBNE bit is set */ | ||||||
|  |                         if (i2c_flag_get(I2C0, I2C_FLAG_RBNE)) { | ||||||
|  |                             /* read a byte from the EEPROM */ | ||||||
|  |                             *data = i2c_data_receive(I2C0); | ||||||
|  |                             /* point to the next location where the byte read will be saved */ | ||||||
|  |                             data++; | ||||||
|  |                             /* decrement the read bytes counter */ | ||||||
|  |                             number_of_byte--; | ||||||
|  |                             timeout = 0; | ||||||
|  |                         } | ||||||
|  |                         if (timeout > I2C_TIME_OUT) { | ||||||
|  |                             timeout = 0; | ||||||
|  |                             state = I2C_START; | ||||||
|  |                             read_cycle = 0; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                             printf("i2c master sends data timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_STOP; | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case I2C_STOP: | ||||||
|  |                 /* i2c master sends STOP signal successfully */ | ||||||
|  |                 while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { | ||||||
|  |                     timeout++; | ||||||
|  |                 } | ||||||
|  |                 if (timeout < I2C_TIME_OUT) { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_END; | ||||||
|  |                     i2c_timeout_flag = I2C_OK; | ||||||
|  |                 } else { | ||||||
|  |                     timeout = 0; | ||||||
|  |                     state = I2C_START; | ||||||
|  |                     read_cycle = 0; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                     printf("i2c master sends stop signal timeout in READ!\n"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 state = I2C_START; | ||||||
|  |                 read_cycle = 0; | ||||||
|  |                 i2c_timeout_flag = I2C_OK; | ||||||
|  |                 timeout = 0; | ||||||
|  | #ifdef DEBUG_VERBOES | ||||||
|  |                 printf("i2c master sends start signal in READ.\n"); | ||||||
|  | #endif | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return I2C_END; | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								src/led.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/led.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "led.h" | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      configure LED | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void led_config(void) { | ||||||
|  |     rcu_periph_clock_enable(LED_RCU); | ||||||
|  |  | ||||||
|  |     gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); | ||||||
|  |     gpio_output_options_set(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_PIN); | ||||||
|  |     gpio_bit_write(LED_PORT, LED_PIN, SET); | ||||||
|  |  | ||||||
|  |     rcu_periph_clock_enable(LED_BLINK_TIMER_RCU); | ||||||
|  |     timer_deinit(LED_BLINK_TIMER); | ||||||
|  |  | ||||||
|  |     timer_parameter_struct timer_initpara; | ||||||
|  |     timer_struct_para_init(&timer_initpara); | ||||||
|  |     timer_initpara.prescaler = 7199; | ||||||
|  |     timer_initpara.alignedmode = TIMER_COUNTER_EDGE; | ||||||
|  |     timer_initpara.counterdirection = TIMER_COUNTER_UP; | ||||||
|  |     timer_initpara.period = 9999; | ||||||
|  |     timer_initpara.clockdivision = TIMER_CKDIV_DIV1; | ||||||
|  |     timer_init(LED_BLINK_TIMER, &timer_initpara); | ||||||
|  |  | ||||||
|  |     timer_auto_reload_shadow_enable(LED_BLINK_TIMER); | ||||||
|  |     timer_interrupt_enable(LED_BLINK_TIMER, TIMER_INT_UP); | ||||||
|  |  | ||||||
|  |     timer_enable(LED_BLINK_TIMER); | ||||||
|  |  | ||||||
|  |     nvic_irq_enable(LED_BLINK_IRQ, 2); | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -5,12 +5,6 @@ | |||||||
|     \version 2024-02-22, V2.1.0, firmware for GD32E23x |     \version 2024-02-22, V2.1.0, firmware for GD32E23x | ||||||
| */ | */ | ||||||
| #include "main.h" | #include "main.h" | ||||||
| #include <stdio.h> |  | ||||||
| #include "gd32e23x.h" |  | ||||||
| #include "systick.h" |  | ||||||
| #include "gd32e23x_libopt.h" |  | ||||||
|  |  | ||||||
| #include "peripheral.h" |  | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|     \brief      main function |     \brief      main function | ||||||
| @@ -18,19 +12,26 @@ | |||||||
|     \param[out] none |     \param[out] none | ||||||
|     \retval     none |     \retval     none | ||||||
| */ | */ | ||||||
| int main(void) | int main(void) { | ||||||
| { |     // setbuf(stdout, NULL); | ||||||
|     /* configure systick */ |     /* configure systick */ | ||||||
|     systick_config(); |     systick_config(); | ||||||
|     usart_config(); |     /* configure USART */ | ||||||
|     led_blink_config(); |     // rs485_config(); | ||||||
|  |     /* configure LED */ | ||||||
|  |     // led_config(); | ||||||
|  |  | ||||||
|     delay_ms(5000); |  | ||||||
|     printf("system start!\r\n"); |     printf("system start!\r\n"); | ||||||
|  |  | ||||||
|  |     rcu_periph_clock_enable(RCU_GPIOA); | ||||||
|  |  | ||||||
|  |     gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7); | ||||||
|  |     gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_7); | ||||||
|  |     gpio_bit_write(GPIOA, GPIO_PIN_7, SET); | ||||||
|  |  | ||||||
|     while(1){ |     while(1){ | ||||||
|     printf("hello world!\r\n"); |     printf("hello world!\r\n"); | ||||||
|     delay_ms(5000); |     delay_ms(1000); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,63 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by yelv1 on 24-9-22. |  | ||||||
| // |  | ||||||
| #include "peripheral.h" |  | ||||||
| #include "gd32e23x.h" |  | ||||||
|  |  | ||||||
| void usart_config(void) |  | ||||||
| { |  | ||||||
|     rcu_periph_clock_enable(RCU_GPIOA); |  | ||||||
|     rcu_periph_clock_enable(RCU_USART0); |  | ||||||
|  |  | ||||||
|     gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_3); |  | ||||||
|     gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_2); |  | ||||||
|  |  | ||||||
|     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3); |  | ||||||
|     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_3); |  | ||||||
|     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2); |  | ||||||
|     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_2); |  | ||||||
|  |  | ||||||
|     usart_deinit(USART0); |  | ||||||
|     usart_baudrate_set(USART0, 115200U); |  | ||||||
|     usart_receive_config(USART0, USART_RECEIVE_ENABLE); |  | ||||||
|     usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); |  | ||||||
|  |  | ||||||
|     usart_enable(USART0); |  | ||||||
|  |  | ||||||
|     gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4); |  | ||||||
|     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4); |  | ||||||
|  |  | ||||||
|     gpio_bit_write(GPIOA, GPIO_PIN_4, SET); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /*! |  | ||||||
|     \brief      led blink configuration |  | ||||||
|     \param[in]  none |  | ||||||
|     \param[out] none |  | ||||||
|     \retval     none |  | ||||||
| */ |  | ||||||
| void led_blink_config(void) |  | ||||||
| { |  | ||||||
|     rcu_periph_clock_enable(RCU_GPIOB); |  | ||||||
|  |  | ||||||
|     gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1); |  | ||||||
|     gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_1); |  | ||||||
|     gpio_bit_write(GPIOB, GPIO_PIN_1, SET); |  | ||||||
|  |  | ||||||
|     rcu_periph_clock_enable(RCU_TIMER13); |  | ||||||
|     timer_deinit(RCU_TIMER13); |  | ||||||
|  |  | ||||||
|     timer_parameter_struct timer_initpara; |  | ||||||
|     timer_struct_para_init(&timer_initpara); |  | ||||||
|     timer_initpara.prescaler        =7199; |  | ||||||
|     timer_initpara.alignedmode      =TIMER_COUNTER_EDGE; |  | ||||||
|     timer_initpara.counterdirection =TIMER_COUNTER_UP; |  | ||||||
|     timer_initpara.period           =999; |  | ||||||
|     timer_initpara.clockdivision    =TIMER_CKDIV_DIV1; |  | ||||||
|     timer_init(TIMER13, &timer_initpara); |  | ||||||
|  |  | ||||||
|     timer_auto_reload_shadow_enable(TIMER13); |  | ||||||
|     timer_interrupt_enable(TIMER13, TIMER_INT_UP); |  | ||||||
|     nvic_irq_enable(TIMER13_IRQn, 0); |  | ||||||
|     timer_enable(TIMER13); |  | ||||||
| } |  | ||||||
							
								
								
									
										49
									
								
								src/rs485.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/rs485.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-3. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "rs485.h" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief  configure the USART0 | ||||||
|  |  * @param  none | ||||||
|  |  * @retval none | ||||||
|  |  */ | ||||||
|  | void usart_config(void) { | ||||||
|  |     rcu_periph_clock_enable(RS485_GPIO_RCU); | ||||||
|  |     rcu_periph_clock_enable(RS485_RCU); | ||||||
|  |  | ||||||
|  |     gpio_af_set(RS485_GPIO_PORT, GPIO_AF_1, GPIO_PIN_2 | GPIO_PIN_3); | ||||||
|  |  | ||||||
|  |     /* configure USART Tx&Rx as alternate function push-pull */ | ||||||
|  |     gpio_mode_set(RS485_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, RS485_TX_PIN | RS485_RX_PIN); | ||||||
|  |     gpio_output_options_set(RS485_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, RS485_TX_PIN | RS485_RX_PIN); | ||||||
|  |  | ||||||
|  |     /* USART configure */ | ||||||
|  |     usart_deinit(RS485_PHY); | ||||||
|  |     usart_baudrate_set(RS485_PHY, RS485_BAUDRATE); | ||||||
|  |     usart_receive_config(RS485_PHY, USART_RECEIVE_ENABLE); | ||||||
|  |     usart_transmit_config(RS485_PHY, USART_TRANSMIT_ENABLE); | ||||||
|  |  | ||||||
|  |     usart_enable(RS485_PHY); | ||||||
|  |  | ||||||
|  |     nvic_irq_enable(USART0_IRQn, 0); | ||||||
|  |     usart_interrupt_enable(RS485_PHY, USART_INT_RBNE); | ||||||
|  |     usart_interrupt_enable(RS485_PHY, USART_INT_IDLE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief  configure the RS485(MAX13487EESA) | ||||||
|  |  * @param  none | ||||||
|  |  * @retval none | ||||||
|  |  */ | ||||||
|  | void rs485_config(void) { | ||||||
|  |     usart_config(); | ||||||
|  |  | ||||||
|  |     rcu_periph_clock_enable(RS485_GPIO_RCU); | ||||||
|  |  | ||||||
|  |     /* configure RS485 EN Pin */ | ||||||
|  |     gpio_mode_set(RS485_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS485_EN_PIN); | ||||||
|  |     gpio_output_options_set(RS485_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RS485_EN_PIN); | ||||||
|  |     gpio_bit_write(RS485_GPIO_PORT, RS485_EN_PIN, SET); // auto direction control | ||||||
|  | } | ||||||
							
								
								
									
										217
									
								
								src/soft_i2c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/soft_i2c.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | |||||||
|  | // | ||||||
|  | // Created by dell on 24-12-28. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "soft_i2c.h" | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      delay | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_delay(void) { | ||||||
|  |     delay_us(20); // Adjust delay as needed | ||||||
|  |     /* delay to freq | ||||||
|  |      *  15KHz: delay_us(20); | ||||||
|  |      *  65KHz: delay_us(1); | ||||||
|  |      */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      configure the software IIC GPIO | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_config(void) { | ||||||
|  |     rcu_periph_clock_enable(RCU_GPIO_I2C); | ||||||
|  |  | ||||||
|  |     gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SCL_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); | ||||||
|  |  | ||||||
|  |     gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN); | ||||||
|  |     gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); | ||||||
|  |  | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      generate I2C start signal | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_start(void) { | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SDA_LOW(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_LOW(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      generate I2C stop signal | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_stop(void) { | ||||||
|  |     // sda_out(); | ||||||
|  |     I2C_SCL_LOW(); | ||||||
|  |     I2C_SDA_LOW(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      send I2C ACK signal | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_send_ack(void) { | ||||||
|  |     // sda_out(); | ||||||
|  |     I2C_SDA_LOW(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_LOW(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      send I2C NACK signal | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_send_nack(void) { | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_LOW(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      wait I2C ACK signal | ||||||
|  |     \param[in]  none | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     0: ACK received, 1: ACK not received | ||||||
|  | */ | ||||||
|  | uint8_t soft_i2c_wait_ack(void) { | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     I2C_SCL_HIGH(); | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     uint8_t ack = !I2C_SDA_READ(); | ||||||
|  |     I2C_SCL_LOW(); | ||||||
|  |     return ack; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      send a byte via I2C | ||||||
|  |     \param[in]  byte: byte to be sent | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     none | ||||||
|  | */ | ||||||
|  | void soft_i2c_send_byte(uint8_t byte) { | ||||||
|  |     // sda_out(); | ||||||
|  |     for (int i = 0; i < 8; i++) { | ||||||
|  |         if (byte & 0x80) { | ||||||
|  |             I2C_SDA_HIGH(); | ||||||
|  |         } else { | ||||||
|  |             I2C_SDA_LOW(); | ||||||
|  |         } | ||||||
|  |         byte <<= 1; | ||||||
|  |         soft_i2c_delay(); | ||||||
|  |         I2C_SCL_HIGH(); | ||||||
|  |         soft_i2c_delay(); | ||||||
|  |         I2C_SCL_LOW(); | ||||||
|  |         soft_i2c_delay(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |     \brief      receive a byte via I2C | ||||||
|  |     \param[in]  ack: 1: send ACK, 0: send NACK | ||||||
|  |     \param[out] none | ||||||
|  |     \retval     received byte | ||||||
|  | */ | ||||||
|  | uint8_t soft_i2c_receive_byte(uint8_t ack) { | ||||||
|  |     uint8_t byte = 0; | ||||||
|  |     I2C_SDA_HIGH(); | ||||||
|  |     for (int i = 0; i < 8; i++) { | ||||||
|  |         byte <<= 1; | ||||||
|  |         I2C_SCL_HIGH(); | ||||||
|  |         soft_i2c_delay(); | ||||||
|  |         if (I2C_SDA_READ()) { | ||||||
|  |             byte |= 0x01; | ||||||
|  |         } | ||||||
|  |         I2C_SCL_LOW(); | ||||||
|  |         soft_i2c_delay(); | ||||||
|  |     } | ||||||
|  |     if (ack) { | ||||||
|  |         soft_i2c_send_ack(); | ||||||
|  |     } else { | ||||||
|  |         soft_i2c_send_nack(); | ||||||
|  |     } | ||||||
|  |     return byte; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data[2]) { | ||||||
|  |     soft_i2c_start(); | ||||||
|  |     soft_i2c_send_byte(slave_addr); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_send_byte(reg_addr); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_send_byte(data[0]); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_send_byte(data[1]); | ||||||
|  |     if (soft_i2c_wait_ack()){} | ||||||
|  |     soft_i2c_stop(); | ||||||
|  |     return SOFT_I2C_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t soft_i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data) | ||||||
|  | { | ||||||
|  |     soft_i2c_start(); | ||||||
|  |     soft_i2c_send_byte(slave_addr); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_send_byte(reg_addr); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_start(); | ||||||
|  |     soft_i2c_send_byte(slave_addr | 0x01); | ||||||
|  |     if (!soft_i2c_wait_ack()) { | ||||||
|  |         soft_i2c_stop(); | ||||||
|  |         return SOFT_I2C_FAIL; | ||||||
|  |     } | ||||||
|  |     soft_i2c_delay(); | ||||||
|  |     data[0] = soft_i2c_receive_byte(1); | ||||||
|  |     data[1] = soft_i2c_receive_byte(0); | ||||||
|  |     soft_i2c_stop(); | ||||||
|  |     return SOFT_I2C_OK; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user