- #include "eeprom.h"
- #define I2C_DIR_TRANSMIT 0x00
- #define I2C_DIR_RECEIVE 0x01
- #define I2C_ACK_TIMEOUT 64
- #define I2C_SCL_HIGH() GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_Pin_SET)
- #define I2C_SCL_LOW() GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_Pin_RESET)
- #define I2C_SDA_HIGH() GPIO_WritePin(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN, GPIO_Pin_SET)
- #define I2C_SDA_LOW() GPIO_WritePin(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN, GPIO_Pin_RESET)
- #define I2C_SDA_READ GPIO_ReadPin(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN)
- #define I2C_DALEY_US 5
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] i2c address direction
- */
- void i2c_config(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- /* i2c gpio clock enable */
- __RCC_GPIOB_CLK_ENABLE();
-
- /* gpio configuration */
- GPIO_InitStruct.IT = GPIO_IT_NONE;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
- /* configure i2c pins: scl */
- GPIO_InitStruct.Pins = I2Cx_SCL_PIN;
- GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
- /* configure i2c pins: sda */
- GPIO_InitStruct.Pins = I2Cx_SDA_PIN;
- GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
- I2C_SDA_HIGH();
- I2C_SCL_HIGH();
- }
- /**
- * @brief used to set the i2c clock frequency.
- * @param none.
- * @retval none.
- */
- void i2c_delay(void)
- {
- uint8_t i = 0;
- uint8_t j = 48;
- for (i = 0; i< I2C_DALEY_US; i++) {
- while(j--);
- }
- }
- /**
- * @brief 循环延时
- *
- * @param nCount
- */
- void Delay(__IO uint16_t nCount)
- {
- /* Decrement nCount value */
- while (nCount != 0)
- {
- nCount--;
- }
- }
- /**
- * @brief used to generate start conditions.
- * @param none.
- * @retval none.
- */
- void i2c_start(void)
- {
- i2c_delay();
-
- I2C_SDA_HIGH();
- I2C_SCL_HIGH();
- i2c_delay();
-
- I2C_SDA_LOW();
- i2c_delay();
-
- I2C_SCL_LOW();
- i2c_delay();
- }
- /**
- * @brief used to generate stop conditions.
- * @param none.
- * @retval none.
- */
- void i2c_stop(void)
- {
- I2C_SCL_LOW();
- I2C_SDA_LOW();
- i2c_delay();
-
- I2C_SCL_HIGH();
- i2c_delay();
-
- I2C_SDA_HIGH();
- i2c_delay();
- }
- /**
- * @brief used to generate ack conditions.
- * @param none.
- * @retval none.
- */
- void i2c_ack(void)
- {
- I2C_SCL_LOW();
- I2C_SDA_LOW();
- i2c_delay();
-
- I2C_SCL_HIGH();
- i2c_delay();
-
- I2C_SCL_LOW();
- i2c_delay();
- }
- /**
- * @brief used to generate nack conditions.
- * @param none.
- * @retval none.
- */
- void i2c_no_ack(void)
- {
- I2C_SCL_LOW();
- I2C_SDA_HIGH();
- i2c_delay();
-
- I2C_SCL_HIGH();
- i2c_delay();
-
- I2C_SCL_LOW();
- i2c_delay();
- }
- /**
- * @brief used to wait ack conditions.
- * @param none.
- * @retval ack receive status.
- * - 1: no ack received.
- * - 0: ack received.
- */
- uint8_t i2c_wait_ack(uint8_t timeout)
- {
- I2C_SCL_LOW();
- I2C_SDA_HIGH();
-
- i2c_delay();
-
- while(timeout)
- {
- if (I2C_SDA_READ == 0)
- {
- I2C_SCL_HIGH();
-
- i2c_delay();
-
- I2C_SCL_LOW();
-
- return 0;
- }
-
- i2c_delay();
-
- timeout--;
- }
-
- return 1;
- }
- /**
- * @brief send a byte.
- * @param data: byte to be transmitted.
- * @retval none.
- */
- void i2c_send_byte(uint8_t data)
- {
- uint8_t i = 8;
-
- I2C_SCL_LOW(); //
- while (i--)
- {
- if (data & 0x80)
- {
- I2C_SDA_HIGH();
- }
- else
- {
- I2C_SDA_LOW();
- }
-
- i2c_delay();
-
- I2C_SCL_HIGH();
- i2c_delay();
- I2C_SCL_LOW();
- i2c_delay();
-
- data <<= 1;
- }
- }
- /**
- * @brief receive a byte.
- * @param data: byte to be received.
- * @retval none.
- */
- uint8_t i2c_receive_byte(void)
- {
- uint8_t i = 8;
- uint8_t byte = 0;
- I2C_SDA_HIGH();
- I2C_SCL_LOW();
-
- while (i--)
- {
- byte <<= 1;
- I2C_SCL_HIGH();
- i2c_delay();
-
- byte |= I2C_SDA_READ;
- I2C_SCL_LOW();
- i2c_delay();
- }
- return byte;
- }
- uint8_t i2c_WriteByte(uint8_t I2C_Addr,uint8_t addr,uint8_t data)
- {
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_TRANSMIT);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
-
- return 1;
- }
- i2c_send_byte(addr); //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",addr);
- return 1;
- }
- i2c_send_byte(data);
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",data);
- return 1;
- }
-
- i2c_stop(); //
- Delay(0xffff);
- Delay(0xffff);
- Delay(0xffff);
- printf("write ok\r\n");
- return 0;
- }
- uint8_t i2c_ReadCurrentAddrByte(uint8_t I2C_Addr)
- {
- uint8_t data;
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_RECEIVE);; //锟斤拷锟酵从伙拷锟斤拷址
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
-
- return 1;
- }
- data = i2c_receive_byte();
- i2c_no_ack();
- i2c_stop(); //
- printf("receive1 ok\r\n");
- return data;
- }
- uint8_t i2c_ReadByte(uint8_t I2C_Addr,uint8_t addr)
- {
- uint8_t data;
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_TRANSMIT);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
-
- return 1;
- }
- i2c_send_byte((uint8_t)addr); //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",addr);
- return 1;
- }
-
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_RECEIVE);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",I2C_Addr);
- return 1;
- }
- data = i2c_receive_byte();
- i2c_no_ack();
- i2c_stop(); //
- printf("receive ok\r\n");
- return data;
- }
- uint8_t i2c_ReadMultByte(uint8_t I2C_Addr,uint16_t addr,uint8_t length, uint8_t *pdata)
- {
- uint8_t i = 0;
-
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_TRANSMIT);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
-
- return 1;
- }
- i2c_send_byte((uint8_t)addr); //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",addr);
- return 1;
- }
-
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_RECEIVE);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x \r\n",I2C_Addr);
- return 1;
- }
-
- for(i = 0; i< length; i++) {
-
- pdata[i] = i2c_receive_byte();
-
- if (i < (length - 1))
- {
- i2c_ack();
- }
- else
- {
- i2c_no_ack();
- }
- }
- i2c_stop(); //
- printf("mul receive ok\r\n");
- return 0;
- }
- uint8_t i2c_WriteMultByte(uint8_t I2C_Addr,uint16_t addr,uint8_t length, uint8_t *pdata)
- {
- uint8_t i = 0;
-
- i2c_start();
- i2c_send_byte(I2C_Addr | I2C_DIR_TRANSMIT);; //
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
-
- return 1;
- }
-
- i2c_send_byte((uint8_t)addr); //
- printf("addr high %x",(uint8_t)(addr));
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %x\r\n",addr);
- return 1;
- }
-
- for(i = 0; i< length; i++) {
- i2c_send_byte(pdata[i]);
- if (i2c_wait_ack(I2C_ACK_TIMEOUT) == 1)
- {
- i2c_stop();
- printf("EEPROM %d %x \r\n",i,addr);
- return 1;
- }
- }
- i2c_stop(); //
- printf("write ok\r\n");
- Delay(0xffff);
- return 0;
- }
2)、.h代码
- #ifndef __EEPROM_H__
- #define __EEPROM_H__
- #include "..\inc\main.h"
- #define I2Cx_SCL_PIN GPIO_PIN_6
- #define I2Cx_SCL_GPIO_PORT CW_GPIOB
- #define I2Cx_SDA_PIN GPIO_PIN_7
- #define I2Cx_SDA_GPIO_PORT CW_GPIOB
- /** @defgroup I2C_library_exported_functions
- * @{
- */
- void i2c_config(void);
- void delay_us(uint32_t us);
- void Delay(__IO uint16_t nCount);
- uint8_t i2c_WriteByte(uint8_t I2C_Addr,uint8_t addr,uint8_t data);
- uint8_t i2c_ReadCurrentAddrByte(uint8_t I2C_Addr);
- uint8_t i2c_ReadByte(uint8_t I2C_Addr,uint8_t addr);
- uint8_t i2c_ReadMultByte(uint8_t I2C_Addr,uint16_t addr,uint8_t length, uint8_t *pdata);
- uint8_t i2c_WriteMultByte(uint8_t I2C_Addr,uint16_t addr,uint8_t length, uint8_t *pdata);
- #endif
3)、测试主程序
- #include "..\inc\main.h"
- /******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- //UARTx
- #define DEBUG_USARTx CW_UART1
- #define DEBUG_USART_CLK RCC_APB2_PERIPH_UART1
- #define DEBUG_USART_APBClkENx RCC_APBPeriphClk_Enable2
- #define DEBUG_USART_BaudRate 9600
- #define DEBUG_USART_UclkFreq 8000000
- #define LED_GPIO_PORT CW_GPIOB
- #define LED_GPIO_PINS GPIO_PIN_8 | GPIO_PIN_9
- //UARTx GPIO
- #define DEBUG_USART_GPIO_CLK RCC_AHB_PERIPH_GPIOA
- #define DEBUG_USART_TX_GPIO_PORT CW_GPIOA
- #define DEBUG_USART_TX_GPIO_PIN GPIO_PIN_8
- #define DEBUG_USART_RX_GPIO_PORT CW_GPIOA
- #define DEBUG_USART_RX_GPIO_PIN GPIO_PIN_9
- //GPIO AF
- #define DEBUG_USART_AFTX PA08_AFx_UART1TXD()
- #define DEBUG_USART_AFRX PA09_AFx_UART1RXD()
- /******************************************************************************
- * Global variable definitions (declared in header file with 'extern')
- ******************************************************************************/
- uint8_t test_data[] = {0x01,0x02,0x03};
- uint8_t test_readdata[3] = {0x00};
- /******************************************************************************
- * Local type definitions ('typedef')
- ******************************************************************************/
- /******************************************************************************
- * Local function prototypes ('static')
- ******************************************************************************/
- void RCC_Configuration(void);
- void GPIO_Configuration(void);
- void UART_Configuration(void);
- #ifdef __GNUC__
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
- set to 'Yes') calls __io_putchar() */
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif /* __GNUC__ */
- /******************************************************************************
- * Local variable definitions ('static') *
- ******************************************************************************/
- /******************************************************************************
- * Local pre-processor symbols/macros ('#define')
- ******************************************************************************/
- /*****************************************************************************
- * Function implementation - global ('extern') and local ('static')
- ******************************************************************************/
- /**
- ******************************************************************************
- ** \brief Main function of project
- **
- ** \return uint32_t return value, if needed
- **
- ******************************************************************************/
- int32_t main(void)
- {
- //配置RCC
- RCC_Configuration();
- //配置GPIO
- GPIO_Configuration();
- //i2c_config();
- //配置UART
- UART_Configuration();
-
- printf("\r\n use CW32L031 simulate I2C READ EEPROM Example\r\n");
-
- while(1)
- {
- if (GPIO_ReadPin(CW_GPIOA, GPIO_PIN_1) == 0) {
- i2c_WriteByte(0xA0,0x01,0x5A);
- i2c_WriteMultByte(0xA0,0x05,3,test_data);
- }
-
- if (GPIO_ReadPin(CW_GPIOA, GPIO_PIN_2) == 0) {
- printf("data:%x \r\n",i2c_ReadByte(0xA0,0x01));
- i2c_ReadMultByte(0xA0,0x05,3,test_readdata);
- for(int i = 0;i < 3; i++) {
- printf("test_readdata[%d] = %x \r\n",i,test_readdata[i]);
- }
-
- }
-
- GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PINS);
- Delay(0xFFFF);
- }
- }
- /**
- * @brief 配置RCC
- *
- */
- void RCC_Configuration(void)
- {
- //SYSCLK = HSI = 8MHz = HCLK = PCLK
- RCC_HSI_Enable(RCC_HSIOSC_DIV6);
- //外设时钟使能
- RCC_AHBPeriphClk_Enable(DEBUG_USART_GPIO_CLK, ENABLE);
- DEBUG_USART_APBClkENx(DEBUG_USART_CLK, ENABLE);
- RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOB,ENABLE);
- __RCC_GPIOA_CLK_ENABLE();
- }
- /**
- * @brief 配置GPIO
- *
- */
- void GPIO_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
-
- //UART TX RX 复用
- DEBUG_USART_AFTX;
- DEBUG_USART_AFRX;
- GPIO_InitStructure.Pins = DEBUG_USART_TX_GPIO_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
- GPIO_InitStructure.Pins = GPIO_PIN_1 | GPIO_PIN_2;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
- GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = DEBUG_USART_RX_GPIO_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
- GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pins = LED_GPIO_PINS;
-
- GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
-
-
- /* gpio configuration */
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
- /* configure i2c pins: scl */
- GPIO_InitStructure.Pins = I2Cx_SCL_PIN;
- GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStructure);
- /* configure i2c pins: sda */
- GPIO_InitStructure.Pins = I2Cx_SDA_PIN;
- GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStructure);
- GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_Pin_SET);
- GPIO_WritePin(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN, GPIO_Pin_SET);
- }
- /**
- * @brief 配置UART
- *
- */
- void UART_Configuration(void)
- {
- USART_InitTypeDef USART_InitStructure = {0};
- USART_InitStructure.USART_BaudRate = DEBUG_USART_BaudRate;
- USART_InitStructure.USART_Over = USART_Over_16;
- USART_InitStructure.USART_Source = USART_Source_PCLK;
- USART_InitStructure.USART_UclkFreq = DEBUG_USART_UclkFreq;
- USART_InitStructure.USART_StartBit = USART_StartBit_FE;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No ;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(DEBUG_USARTx, &USART_InitStructure);
- }
- // KEIL
- /**
- * @brief Retargets the C library printf function to the USART.
- *
- */
- PUTCHAR_PROTOTYPE
- {
- USART_SendData_8bit(DEBUG_USARTx, (uint8_t)ch);
- while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
- return ch;
- }
- // IAR
- size_t __write(int handle, const unsigned char * buffer, size_t size)
- {
- size_t nChars = 0;
- if (buffer == 0)
- {
- /*
- * This means that we should flush internal buffers. Since we
- * don't we just return. (Remember, "handle" == -1 means that all
- * handles should be flushed.)
- */
- return 0;
- }
- for (/* Empty */; size != 0; --size)
- {
- USART_SendData_8bit(DEBUG_USARTx, *buffer++);
- while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
- ++nChars;
- }
- return nChars;
- }
三、实际测试串口输出
单字节写入5a,单字节读出来也是5a;
多字节写入01 02 03;多字节读出来也是01 02 03