2023-01-24 14:55:30 +08:00

260 lines
6.9 KiB
C

/***
* Demo: I2C - AT24C32 Read/Write
*
* PY32
* PF1 SCL
* PF0 SDA
*/
#include <string.h>
#include "main.h"
#include "py32f0xx_bsp_printf.h"
#define MASTER_ADDRESS 0xA0
#define AT24C_ADDRESS 0xAE
#define AT24C_MEM_ADDRESS 0x80
#define I2C_STATE_READY 0
#define I2C_STATE_BUSY_TX 1
#define I2C_STATE_BUSY_RX 2
/*
* EERPOM data address length
*
* 1-byte: AT24C01 - AT24C16
* 2-byte: AT24C32+
*/
#define AT24C_DATA_ADDR_8B 0
#define AT24C_DATA_ADDR_16B 1
#define AT24C_DATA_ADDR_LEN AT24C_DATA_ADDR_16B
#define SIZE sizeof(test_text)
const uint8_t test_text[]={"I2C read/write test"};
__IO uint32_t i2cState = I2C_STATE_READY;
static void APP_SystemClockConfig(void);
static void APP_I2CConfig(void);
void APP_I2C_Transmit(uint8_t devAddress, uint16_t memAddress, uint8_t *pData, uint16_t len);
uint8_t APP_I2C_ReceiveByte(uint16_t devAddress, uint16_t memAddress);
void AT24CXX_Read(uint16_t dataAddr, uint8_t *pBuffer, uint16_t len)
{
while (len--)
{
*pBuffer++ = APP_I2C_ReceiveByte(AT24C_ADDRESS, dataAddr++);
LL_mDelay(5);
}
}
void AT24CXX_Write(uint16_t dataAddr, uint8_t *pBuffer, uint16_t len)
{
while (len--)
{
APP_I2C_Transmit(AT24C_ADDRESS, dataAddr++, pBuffer++, 1);
// Writing might halt if delay is too short
LL_mDelay(5);
}
}
int main(void)
{
uint8_t buf[SIZE];
APP_SystemClockConfig();
BSP_USART_Config(115200);
printf("I2C Demo: AT24C32\r\nClock: %ld\r\n", SystemCoreClock);
APP_I2CConfig();
printf("Start writing...");
AT24CXX_Write(AT24C_MEM_ADDRESS, (uint8_t *)test_text, SIZE);
printf("succ\r\n");
printf("Start reading...");
AT24CXX_Read(AT24C_MEM_ADDRESS, buf, SIZE);
printf("read: %s\r\n", buf);
while(1);
}
static void APP_I2CConfig(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOF);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
// PF1 SCL
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct);
// PF0 SDA
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Alternate = LL_GPIO_AF_12;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
LL_I2C_InitTypeDef I2C_InitStruct;
/*
* Clock speed:
* - standard = 100khz
* - fast = 400khz
*/
I2C_InitStruct.ClockSpeed = LL_I2C_MAX_SPEED_FAST;
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_16_9;
I2C_InitStruct.OwnAddress1 = MASTER_ADDRESS;
I2C_InitStruct.TypeAcknowledge = LL_I2C_NACK;
LL_I2C_Init(I2C1, &I2C_InitStruct);
}
void APP_I2C_Transmit(uint8_t devAddress, uint16_t memAddress, uint8_t *pData, uint16_t len)
{
while (i2cState == I2C_STATE_BUSY_TX);
LL_I2C_DisableBitPOS(I2C1);
i2cState = I2C_STATE_BUSY_TX;
/* Start */
LL_I2C_GenerateStartCondition(I2C1);
while (LL_I2C_IsActiveFlag_SB(I2C1) != 1);
/* Send slave address */
LL_I2C_TransmitData8(I2C1, (devAddress & (uint8_t)(~0x01)));
while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1);
LL_I2C_ClearFlag_ADDR(I2C1);
/* Send memory address */
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
#if (AT24C_DATA_ADDR_LEN == AT24C_DATA_ADDR_8B)
LL_I2C_TransmitData8(I2C1, (uint8_t)(memAddress & 0x00FF));
#elif (AT24C_DATA_ADDR_LEN == AT24C_DATA_ADDR_16B)
LL_I2C_TransmitData8(I2C1, (uint8_t)((memAddress & 0xFF00) >> 8));
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
LL_I2C_TransmitData8(I2C1, (uint8_t)(memAddress & 0x00FF));
#endif
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
/* Transfer data */
while (len > 0)
{
while (LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
LL_I2C_TransmitData8(I2C1, *pData++);
len--;
if ((LL_I2C_IsActiveFlag_BTF(I2C1) == 1) && (len != 0U))
{
LL_I2C_TransmitData8(I2C1, *pData++);
len--;
}
while (LL_I2C_IsActiveFlag_BTF(I2C1) != 1);
}
/* Stop */
LL_I2C_GenerateStopCondition(I2C1);
i2cState = I2C_STATE_READY;
}
uint8_t APP_I2C_ReceiveByte(uint16_t devAddress, uint16_t memAddress)
{
uint8_t temp = 0;
LL_I2C_DisableBitPOS(I2C1);
i2cState = I2C_STATE_BUSY_RX;
/* Start */
LL_I2C_GenerateStartCondition(I2C1);
while(LL_I2C_IsActiveFlag_SB(I2C1) != 1);
/* Send slave address */
LL_I2C_TransmitData8(I2C1, (devAddress & (uint8_t)(~0x01)));
while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1);
LL_I2C_ClearFlag_ADDR(I2C1);
/* Send memory address */
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
#if (AT24C_DATA_ADDR_LEN == AT24C_DATA_ADDR_8B)
LL_I2C_TransmitData8(I2C1, (uint8_t)(memAddress & 0x00FF));
#elif (AT24C_DATA_ADDR_LEN == AT24C_DATA_ADDR_16B)
LL_I2C_TransmitData8(I2C1, (uint8_t)((memAddress & 0xFF00) >> 8));
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
LL_I2C_TransmitData8(I2C1, (uint8_t)(memAddress & 0x00FF));
#endif
while(LL_I2C_IsActiveFlag_TXE(I2C1) != 1);
/* Start */
LL_I2C_GenerateStartCondition(I2C1);
while(LL_I2C_IsActiveFlag_SB(I2C1) != 1);
/* Send slave address(read) */
LL_I2C_TransmitData8(I2C1, (devAddress | 0x1));
while(LL_I2C_IsActiveFlag_ADDR(I2C1) != 1);
LL_I2C_ClearFlag_ADDR(I2C1);
while(LL_I2C_IsActiveFlag_RXNE(I2C1) != 1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
temp = LL_I2C_ReceiveData8(I2C1);
LL_I2C_GenerateStopCondition(I2C1);
i2cState = I2C_STATE_READY;
return temp;
}
static void APP_SystemClockConfig(void)
{
LL_UTILS_ClkInitTypeDef UTILS_ClkInitStruct;
LL_RCC_HSI_Enable();
/* Change this value to adjust frequency */
LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_24MHz + 15);
while (LL_RCC_HSI_IsReady() != 1);
UTILS_ClkInitStruct.AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
UTILS_ClkInitStruct.APB1CLKDivider = LL_RCC_APB1_DIV_1;
LL_PLL_ConfigSystemClock_HSI(&UTILS_ClkInitStruct);
/* Re-init frequency of SysTick source, reload = freq/ticks = 48000000/1000 = 48000 */
LL_InitTick(48000000, 1000U);
}
// static void APP_SystemClockConfig(void)
// {
// LL_RCC_HSI_Enable();
// LL_RCC_HSI_SetCalibFreq(LL_RCC_HSICALIBRATION_8MHz);
// while(LL_RCC_HSI_IsReady() != 1);
// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSISYS);
// while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSISYS);
// LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
// /* Update global SystemCoreClock(or through SystemCoreClockUpdate function) */
// LL_SetSystemCoreClock(8000000);
// /* Re-init frequency of SysTick source, reload = freq/ticks = 48000000/1000 = 48000 */
// LL_InitTick(8000000, 1000U);
// }
void APP_ErrorHandler(void)
{
while (1);
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
while (1);
}
#endif /* USE_FULL_ASSERT */