本帖最后由 xld0932 于 2022-10-10 17:30 编辑
HT32F54253 MCU带有3个硬件I2C接口和2个硬件SPI接口,具体的特性如下所示:
内部集成电路——I2C
▆ 支持高达 1 MHz 频率的主从模式
▆ 提供仲裁功能和时钟同步功能
▆ 支持 7-bit 和 10-bit 寻址模式和广播呼叫寻址
▆ 可屏蔽地址功能支持多种从机寻址模式
I2C 模块是一个允许与外部 I2C 接口通信的内部电路,此外部 I2C 接口是一个符合工业标准的用于连接外部硬件的两线串行接口。这两条串行线被称为串行数据线 SDA 和串行时钟线 SCL。 I2C
模块提供三种数据传输速率:即标准模式下的 100 kHz、快速模式下的 400 kHz 和高速模式下的1 MHz。 SCL 周期产生寄存器用于设置不同的占空比得到不同的 SCL 脉冲。
SDA 线是一条双向数据线,它连接整个 I2C 总线,在主机和从机之间用于数据的发送和接收。 I2C模块还具有仲裁检测功能和时钟同步,可防止多个主机试图同时传送数据到 I2C 总线的情况。
串行外设接口——SPI
▆ 支持主机和从机模式
▆ 主机模式频率高达 (fPCLK/2) MHz,从机模式频率高达 (fPCLK/3) MHz
▆ FIFO 深度: 8 级
▆ 多个主机和多个从机工作模式
串行外设接口 SPI 使用 SPI 协议可在主机和从机模式下进行数据发送和接收。 SPI 接口使用 4 个引脚,其中有串行数据输入和输出线, MISO 和 MOSI,时钟线 SCK 和从机选择线 SEL。 SPI 作为主机使用,用 SEL 和 SCK 信号控制数据流来说明数据通信启动和数据采样率。要接收数据字节,数据流在特定的时钟边沿时被锁存且存储在数据寄存器或 RX FIFO。数据发送也是通过类似的方式,但以相反的顺序。模式故障检测功能使其适用于多主机应用。
原理图
实现功能
通过硬件I2C读写扩展板板载的EEPROM芯片,写入随机数据后再进行回读,比较写入数据和读出数据是否相一致;通过硬件SPI操作扩展板板载的SPI FLASH芯片,移植SFUD软件包组件实现对SPI FLASH的读、写、擦除等操作。
实现代码
/* Define to prevent recursive inclusion -------------------------------------*/
#define __EEPROM_C__
/* Includes ------------------------------------------------------------------*/
#include "EEPROM.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
/*******************************************************************************
* [url=home.php?mod=space&uid=247401]@brief[/url]
* @param
* @retval
* [url=home.php?mod=space&uid=93590]@Attention[/url]
*******************************************************************************/
void _I2C_EEPROM_AckPolling(void)
{
uint32_t reg;
/* wait if bus busy */
while(I2C_GetFlagStatus(HT_I2C1, I2C_FLAG_BUSBUSY));
while(1)
{
/* send slave address */
I2C_TargetAddressConfig(HT_I2C1, I2C_EEPROM_DEV_ADDR, I2C_MASTER_WRITE);
/* check status */
while(1)
{
reg = HT_I2C1->SR;
if(reg & I2C_FLAG_ADRS)
{
return;
}
if(reg & I2C_FLAG_RXNACK)
{
I2C_ClearFlag(HT_I2C1, I2C_FLAG_RXNACK);
break;
}
}
}
}
/*******************************************************************************
* [url=home.php?mod=space&uid=247401]@brief[/url]
* @param
* @retval
* [url=home.php?mod=space&uid=93590]@Attention[/url]
*******************************************************************************/
void I2C_EEPROM_BufferRead(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
{
/* check parameters */
Assert_Param(NumByteToRead > 0);
/* acknowledge polling */
_I2C_EEPROM_AckPolling();
/* set EEPROM address */
while (!I2C_CheckStatus(HT_I2C1, I2C_MASTER_TX_EMPTY));
I2C_SendData(HT_I2C1, ReadAddr);
/* send read command */
I2C_TargetAddressConfig(HT_I2C1, I2C_EEPROM_DEV_ADDR, I2C_MASTER_READ);
while(!I2C_CheckStatus( HT_I2C1, I2C_MASTER_SEND_START));
while(!I2C_CheckStatus( HT_I2C1, I2C_MASTER_RECEIVER_MODE));
/* enable master receiver ACK */
if(NumByteToRead > 1)
{
I2C_AckCmd(HT_I2C1, ENABLE);
}
/* sequential read */
while(NumByteToRead)
{
while(!I2C_CheckStatus(HT_I2C1, I2C_MASTER_RX_NOT_EMPTY));
*pBuffer++ = I2C_ReceiveData(HT_I2C1);
if(--NumByteToRead == 1)
{
I2C_AckCmd(HT_I2C1, DISABLE);
}
}
/* end of read */
I2C_GenerateSTOP(HT_I2C1);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void I2C_EEPROM_PageWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
{
/* check parameters */
Assert_Param((NumByteToWrite > 0) &&
((NumByteToWrite <= (I2C_EEPROM_PAGE_SIZE - (WriteAddr & I2C_EEPROM_PAGE_MASK)))));
/* acknowledge polling */
_I2C_EEPROM_AckPolling();
/* set EEPROM address */
while(!I2C_CheckStatus(HT_I2C1, I2C_MASTER_TX_EMPTY));
I2C_SendData(HT_I2C1, WriteAddr);
/* page write */
while(NumByteToWrite--)
{
while(!I2C_CheckStatus(HT_I2C1, I2C_MASTER_TX_EMPTY));
I2C_SendData(HT_I2C1, *pBuffer++);
}
/* end of write */
while(!I2C_CheckStatus(HT_I2C1, I2C_MASTER_TX_EMPTY));
I2C_GenerateSTOP(HT_I2C1);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void I2C_EEPROM_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t Byte2Wr, AvailableByte;
/* check parameters */
Assert_Param(NumByteToWrite <= I2C_EEPROM_CAPACITY);
/* sequential write */
while (NumByteToWrite)
{
AvailableByte = I2C_EEPROM_PAGE_SIZE - (WriteAddr & I2C_EEPROM_PAGE_MASK);
Byte2Wr = (NumByteToWrite > AvailableByte)?(AvailableByte):(NumByteToWrite);
I2C_EEPROM_PageWrite(pBuffer, WriteAddr, Byte2Wr);
pBuffer += Byte2Wr;
WriteAddr = (WriteAddr + Byte2Wr) & I2C_EEPROM_ADDR_MASK;
NumByteToWrite -= Byte2Wr;
}
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void EEPROM_Init(void)
{
I2C_InitTypeDef I2C_InitStructure;
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.PB = 1;
CKCUClock.Bit.PC = 1;
CKCUClock.Bit.I2C1 = 1;
CKCUClock.Bit.AFIO = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
AFIO_GPxConfig(GPIO_PB, AFIO_PIN_15, AFIO_FUN_I2C);
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_0, AFIO_FUN_I2C);
I2C_InitStructure.I2C_GeneralCall = I2C_GENERALCALL_DISABLE;
I2C_InitStructure.I2C_AddressingMode = I2C_ADDRESSING_7BIT;
I2C_InitStructure.I2C_Acknowledge = I2C_ACK_DISABLE;
I2C_InitStructure.I2C_OwnAddress = 0x00;
I2C_InitStructure.I2C_Speed = 400000; //---400k
I2C_InitStructure.I2C_SpeedOffset = 0;
I2C_Init(HT_I2C1, &I2C_InitStructure);
I2C_Cmd(HT_I2C1, ENABLE);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void EEPROM_Demo(void)
{
uint8_t wBuffer[I2C_EEPROM_PAGE_SIZE];
uint8_t rBuffer[I2C_EEPROM_PAGE_SIZE];
for(uint32_t j = 0; j < (I2C_EEPROM_CAPACITY / I2C_EEPROM_PAGE_SIZE); j++)
{
memset(rBuffer, 0, sizeof(rBuffer));
memset(wBuffer, 0, sizeof(wBuffer));
for(uint32_t i = 0; i < I2C_EEPROM_PAGE_SIZE; i++)
{
wBuffer[i] = rand();
}
I2C_EEPROM_BufferWrite((uint8_t *)wBuffer, I2C_EEPROM_PAGE_SIZE * j, I2C_EEPROM_PAGE_SIZE);
printf("\r\nEEPROM Write...[Page%d]", j+1);
for(uint32_t i = 0; i < I2C_EEPROM_PAGE_SIZE; i++)
{
if((i % 10) == 0) printf("\r\n");
printf("0x%02x ", wBuffer[i]);
}
I2C_EEPROM_BufferRead((uint8_t *)rBuffer, I2C_EEPROM_PAGE_SIZE * j, I2C_EEPROM_PAGE_SIZE);
printf("\r\nEEPROM Read....[Page%d]", j+1);
for(uint32_t i = 0; i < I2C_EEPROM_PAGE_SIZE; i++)
{
if((i % 10) == 0) printf("\r\n");
printf("0x%02x ", rBuffer[i]);
}
for(uint32_t i = 0; i < I2C_EEPROM_PAGE_SIZE; i++)
{
if(rBuffer[i] != wBuffer[i])
{
printf("\r\n\r\nEEPROM Read & Write Test Failed!!!"); while(1);
}
}
printf("\t\tCompare Success : %d%%\r\n", (int)((j + 1) * 100) / (I2C_EEPROM_CAPACITY / I2C_EEPROM_PAGE_SIZE));
}
printf("\r\n\r\nEEPROM Read & Write Test Pass!!!");
}
/* Define to prevent recursive inclusion -------------------------------------*/
#define __SPI_FLASH_C__
/* Includes ------------------------------------------------------------------*/
#include "SPI_FLASH.h"
#include <sfud.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SFUD_DEMO_BUFFER_SIZE (512)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t sfud_demo_buf[SFUD_DEMO_BUFFER_SIZE];
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
/*******************************************************************************
* @brief SFUD demo for the first flash device test
* @param addr flash start address
* @param size test flash size
* @param size test flash data buffer
* @retval
* @attention
*******************************************************************************/
void sfud_demo(uint32_t addr, size_t size, uint8_t *data)
{
sfud_err result = SFUD_SUCCESS;
const sfud_flash *flash = sfud_get_device_table() + 0;
size_t i;
/* prepare write data */
for(i = 0; i < size; i++)
{
data[i] = i;
}
/* erase test */
result = sfud_erase(flash, addr, size);
if(result == SFUD_SUCCESS)
{
printf("\r\nErase the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
}
else
{
printf("\r\nErase the %s flash data failed.\r\n", flash->name);
return;
}
/* write test */
result = sfud_write(flash, addr, size, data);
if(result == SFUD_SUCCESS)
{
printf("\r\nWrite the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
}
else
{
printf("\r\nWrite the %s flash data failed.\r\n", flash->name);
return;
}
/* read test */
result = sfud_read(flash, addr, size, data);
if(result == SFUD_SUCCESS)
{
printf("\r\nRead the %s flash data success. Start from 0x%08X, size is %d. The data is:\r\n", flash->name, addr, size);
printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");
for(i = 0; i < size; i++)
{
if((i % 16) == 0)
{
printf("[%08X] ", addr + i);
}
printf("%02X ", data[i]);
if(((i + 1) % 16 == 0) || (i == size - 1))
{
printf("\r\n");
}
}
printf("\r\n");
}
else
{
printf("\r\nRead the %s flash data failed.\r\n", flash->name);
}
/* data check */
for(i = 0; i < size; i++)
{
if(data[i] != i % 256)
{
printf("\r\nRead and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
break;
}
}
if(i == size)
{
printf("\r\nThe %s flash test is success.\r\n", flash->name);
}
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void SPI_FLASH_Init(void)
{
printf("\r\n");
if(sfud_init() == SFUD_SUCCESS)
{
sfud_demo(0, sizeof(sfud_demo_buf), sfud_demo_buf);
}
}
#include <sfud.h>
#include <stdarg.h>
#include "config.h"
static char log_buf[256];
void sfud_log_debug(const char *file, const long line, const char *format, ...);
/**
* SPI write data then read data
*/
static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
size_t read_size) {
sfud_err result = SFUD_SUCCESS;
uint8_t send_data, read_data;
if (write_size) {
SFUD_ASSERT(write_buf);
}
if (read_size) {
SFUD_ASSERT(read_buf);
}
/**
* add your spi write and read code
*/
GPIO_ClearOutBits(HT_GPIOA, GPIO_PIN_8);
for (size_t i = 0; i < (write_size + read_size); i++) {
if (i < write_size) {
send_data = *write_buf++;
} else {
send_data = SFUD_DUMMY_DATA;
}
while(!SPI_GetFlagStatus(HT_SPI1, SPI_FLAG_TXBE));
SPI_SendData(HT_SPI1, send_data);
while(!SPI_GetFlagStatus(HT_SPI1, SPI_FLAG_RXBNE));
read_data = SPI_ReceiveData(HT_SPI1);
if (i >= write_size) {
*read_buf++ = read_data;
}
}
GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_8);
return result;
}
#ifdef SFUD_USING_QSPI
/**
* read flash data by QSPI
*/
static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format,
uint8_t *read_buf, size_t read_size) {
sfud_err result = SFUD_SUCCESS;
/**
* add your qspi read flash data code
*/
return result;
}
#endif /* SFUD_USING_QSPI */
static void rcc_initialize(void) {
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.PA = 1;
CKCUClock.Bit.PB = 1;
CKCUClock.Bit.PC = 1;
CKCUClock.Bit.SPI1 = 1;
CKCUClock.Bit.AFIO = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
static void gpio_initialize(void) {
AFIO_GPxConfig(GPIO_PA, GPIO_PIN_8, AFIO_FUN_GPIO);
AFIO_GPxConfig(GPIO_PA, GPIO_PIN_15, AFIO_FUN_SPI);
AFIO_GPxConfig(GPIO_PB, GPIO_PIN_6, AFIO_FUN_SPI);
AFIO_GPxConfig(GPIO_PC, GPIO_PIN_3, AFIO_FUN_SPI);
GPIO_SetOutBits(HT_GPIOA, GPIO_PIN_8);
GPIO_DirectionConfig(HT_GPIOA, GPIO_PIN_8, GPIO_DIR_OUT);
}
static void spi_device_initialize(void) {
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Mode = SPI_MASTER;
SPI_InitStructure.SPI_FIFO = SPI_FIFO_DISABLE;
SPI_InitStructure.SPI_DataLength = SPI_DATALENGTH_8;
SPI_InitStructure.SPI_SELMode = SPI_SEL_SOFTWARE;
SPI_InitStructure.SPI_SELPolarity = SPI_SELPOLARITY_LOW;
SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_HIGH;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_SECOND;
SPI_InitStructure.SPI_RxFIFOTriggerLevel = 0;
SPI_InitStructure.SPI_TxFIFOTriggerLevel = 0;
#if (LIBCFG_MAX_SPEED > 48000000)
SPI_InitStructure.SPI_ClockPrescaler = 4;
#else
SPI_InitStructure.SPI_ClockPrescaler = 2;
#endif
SPI_Init(HT_SPI1, &SPI_InitStructure);
SPI_SELOutputCmd(HT_SPI1, ENABLE);
SPI_Cmd(HT_SPI1, ENABLE);
}
static void spi_lock(const sfud_spi *spi) {
__disable_irq();
}
static void spi_unlock(const sfud_spi *spi) {
__enable_irq();
}
static void retry_delay_100us(void) {
uint32_t delay = 120;
while (delay--);
}
sfud_err sfud_spi_port_init(sfud_flash *flash) {
sfud_err result = SFUD_SUCCESS;
/**
* add your port spi bus and device object initialize code like this:
* 1. rcc initialize
* 2. gpio initialize
* 3. spi device initialize
* 4. flash->spi and flash->retry item initialize
* flash->spi.wr = spi_write_read; //Required
* flash->spi.qspi_read = qspi_read; //Required when QSPI mode enable
* flash->spi.lock = spi_lock;
* flash->spi.unlock = spi_unlock;
* flash->spi.user_data = &spix;
* flash->retry.delay = null;
* flash->retry.times = 10000; //Required
*/
switch (flash->index) {
case SFUD_FLASH_DEVICE_INDEX:
rcc_initialize();
gpio_initialize();
spi_device_initialize();
flash->spi.wr = spi_write_read;
flash->spi.qspi_read = qspi_read;
flash->spi.lock = spi_lock;
flash->spi.unlock = spi_unlock;
flash->spi.user_data = NULL;
flash->retry.delay = retry_delay_100us;
flash->retry.times = 60 * 10000;
break;
default: break;
}
return result;
}
/**
* This function is print debug info.
*
* @param file the file which has call this function
* @param line the line number which has call this function
* @param format output format
* @param ... args
*/
void sfud_log_debug(const char *file, const long line, const char *format, ...) {
va_list args;
/* args point to the first variable parameter */
va_start(args, format);
printf("[SFUD](%s:%ld) ", file, line);
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
printf("%s\r\n", log_buf);
va_end(args);
}
/**
* This function is print routine info.
*
* @param format output format
* @param ... args
*/
void sfud_log_info(const char *format, ...) {
va_list args;
/* args point to the first variable parameter */
va_start(args, format);
printf("[SFUD]");
/* must use vprintf to print */
vsnprintf(log_buf, sizeof(log_buf), format, args);
printf("%s\r\n", log_buf);
va_end(args);
}
运行结果
软件工程源代码
Project.zip
(896.97 KB)
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|