一般来说,单片机开发中出现次数较多的通信接口主要有U(S)ART,SPI以及I2C,本次测试将主要着眼于以上三种通信接口的开发与测试。
该测例演示了USARTx与PC间通过查询检测标识实现的基础通信。重定向printf函数至USARTx,并使用printf函数输出消息至终端。USARTx可以是USART1或USART2。
该例程使用USART1,PA9为USART_Tx,PA10为USART_Rx,GPIO初始化时PA10设置为浮空输入,PA9为推挽输出。在main函数开头使用USART_InitType结构体对象USART_InitStructure进行USART初始化,即设置波特率、停止位等。
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
设置完成后使用USART_Init()函数进行初始化并使用USART_Enable()函数使能USART,并通过重载fputc()函数进行printf()函数使用USART输出的重定向。
int fputc(int ch, FILE* f)
{
USART_SendData(USARTx, (uint8_t)ch);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET);
return (ch);
}
编译并下载至开发板后,通过串口调试助手可以看到所设置的printf所设置的输出,如下图所示:
该例程中使用SPI1,SPI2分别发送并接收数据,进行CRC校验,若相同则置TransferStatus1与TransferStatus2为PASSED。main函数起始进行SPI1与SPI2的初始化,其中SPI1初始化为主机,SPI2初始化为从机:
/* SPI1 configuration ------------------------------------------------------*/
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_16BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* SPI2 configuration ------------------------------------------------------*/
SPI_InitStructure.SpiMode = SPI_MODE_SLAVE;
SPI_Init(SPI2, &SPI_InitStructure);
随后使用所提供库文件中的SPI_EnableCalculateCrc()函数使能SPI1与SPI2的CRC计算功能,随后通过SPI_Enable()使能SPI1与SPI2,SPI_I2S_TransmitData()函数进行数据的发送,SPI_I2S_ReceiveData()函数读取数据,SPI_TransmitCrcNext()函数使能CRC传输,在最后进行比较,若相同则使TransferStatusx为PASSED。
编译程序并下载至开发板后,连接SPI1与SPI2,打开Keil5 Debug,在Watch界面添加TransferStatus1与TransferStatus2,运行后可以看到其值由0x00 FAILED变为 0x01 PASSED,说明运行成功,如下图所示:(连接后可能出现蜂鸣器持续鸣叫的情况,不用在意)
此例程展示了I2C模块10bit地址模式下的读写操作。
该例程中I2C1为主机,I2C2为从机,分别进行I2C1写I2C2读以及I2C1读I2C2写的测试并比较所写内容和读取内容是否一致,若一致则通过USART串口输出PASSED。main函数起始使用自定义的i2c_master_init()以及i2c_slave_init()两个函数进行I2C主从机的初始化:
int i2c_master_init(void)
{
I2C_InitType i2c1_master;
GPIO_InitType i2c1_gpio;
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
GPIO_ConfigPinRemap(GPIO_RMP_I2C1, ENABLE);
/*PB8 -- SCL; PB9 -- SDA*/
i2c1_gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9;
i2c1_gpio.GPIO_Speed = GPIO_Speed_2MHz;
i2c1_gpio.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitPeripheral(GPIOB, &i2c1_gpio);
I2C_DeInit(I2C1);
i2c1_master.BusMode = I2C_BUSMODE_I2C;
i2c1_master.FmDutyCycle = I2C_FMDUTYCYCLE_2;
i2c1_master.OwnAddr1 = I2C_MASTER_ADDR;
i2c1_master.AckEnable = I2C_ACKEN;
i2c1_master.AddrMode = I2C_ADDR_MODE_10BIT;
i2c1_master.ClkSpeed = 100000; //100K
I2C_Init(I2C1, &i2c1_master);
// int enable
I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);
NVIC_Configuration(1);
I2C_Enable(I2C1, ENABLE);
return 0;
}
int i2c_slave_init(void)
{
I2C_InitType i2c2_slave;
GPIO_InitType i2c2_gpio;
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
/*PB10 -- SCL; PB11 -- SDA*/
i2c2_gpio.Pin = GPIO_PIN_10 | GPIO_PIN_11;
i2c2_gpio.GPIO_Speed = GPIO_Speed_2MHz;
i2c2_gpio.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitPeripheral(GPIOB, &i2c2_gpio);
I2C_DeInit(I2C2);
i2c2_slave.BusMode = I2C_BUSMODE_I2C;
i2c2_slave.FmDutyCycle = I2C_FMDUTYCYCLE_2;
i2c2_slave.OwnAddr1 = I2C_SLAVE_ADDR;
i2c2_slave.AckEnable = I2C_ACKEN;
i2c2_slave.AddrMode = I2C_ADDR_MODE_10BIT;
i2c2_slave.ClkSpeed = 100000; //100K
I2C_Init(I2C2, &i2c2_slave);
// int enable
I2C_ConfigInt(I2C2, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, ENABLE);
NVIC_Configuration(2);
I2C_Enable(I2C2, ENABLE);
return 0;
}
在I2C初始化后便使用库文件中所提供I2C_SendData()函数进行数据发送。
编译该项目并下载至开发板后,连接I2C1与I2C2,打开串口调试助手,复位后出现下图所示情况,说明运行正常:
N32WB452单片机与STM32在相关通讯接口的开发中十分相似,在相关使用中可以充分地代替STM32的作用。
本帖最后由 Eurasia32 于 2022-7-21 12:45 编辑