问题:使用两个GD32E103进行SPI数据传输,主机和从机接收的数组都会移位且不能按照数组顺序接收。
我作为从机,想要实现:主机发送7F 00 00 00 00 00 00 7F,从机传回7F 05 05 05 05 05 05 7F。如果不能实现数组形式传输,也可以一个数一个数的方式传输。
主机代码:
#include "gd32e10x.h"
#include "gd32e10x_eval.h"
//#define SPI_CRC_ENABLE 1
#define ARRAYSIZE 10
#define SET_SPI0_NSS_HIGH gpio_bit_set(GPIOA,GPIO_PIN_4);
#define SET_SPI0_NSS_LOW gpio_bit_reset(GPIOA,GPIO_PIN_4);
uint8_t spi0_send_array[ARRAYSIZE] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
uint8_t spi2_send_array[ARRAYSIZE] = {0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA};
uint8_t spi0_receive_array[ARRAYSIZE] = {0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA};
uint8_t spi2_receive_array[ARRAYSIZE];
uint32_t send_n = 0, receive_n = 0;
uint32_t crc_value1 = 0, crc_value2 = 0;
void rcu_config(void);
void gpio_config(void);
void spi_config(void);
ErrStatus memory_compare(uint8_t *src, uint8_t *dst, uint8_t length);
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* initialize the LEDs */
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
/* enable peripheral clock */
rcu_config();
/* configure GPIO */
gpio_config();
SET_SPI0_NSS_LOW
/* configure SPI */
spi_config();
/* enable SPI */
spi_enable(SPI0);
#if SPI_CRC_ENABLE
/* wait for transmit completed */
while(send_n < ARRAYSIZE) {
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI2, spi2_send_array[send_n]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
spi2_receive_array[receive_n] = spi_i2s_data_receive(SPI2);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n++] = spi_i2s_data_receive(SPI0);
}
/* send the last data */
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI2, spi2_send_array[send_n]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
/* send the CRC value */
spi_crc_next(SPI2);
spi_crc_next(SPI0);
/* receive the last data */
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n] = spi_i2s_data_receive(SPI0);
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
spi2_receive_array[receive_n++] = spi_i2s_data_receive(SPI2);
/* receive the CRC value */
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
crc_value1 = spi_i2s_data_receive(SPI0);
crc_value2 = spi_i2s_data_receive(SPI2);
/* check the CRC error status */
if(SET != spi_i2s_flag_get(SPI0, SPI_FLAG_CRCERR)) {
gd_eval_led_on(LED2);
} else {
gd_eval_led_off(LED2);
}
if(SET != spi_i2s_flag_get(SPI2, SPI_FLAG_CRCERR)) {
gd_eval_led_on(LED3);
} else {
gd_eval_led_off(LED3);
}
#else
/* wait for transmit completed */
while(send_n < ARRAYSIZE) {
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n++] = spi_i2s_data_receive(SPI0);
}
/* compare receive data with send data */
if(ERROR != memory_compare(spi0_receive_array, spi0_send_array, ARRAYSIZE)) {
gd_eval_led_on(LED2);
} else {
gd_eval_led_off(LED2);
}
#endif /* enable CRC function */
while(1) {
}
}
/*!
\brief configure different peripheral clocks
\param[in] none
\param[out] none
\retval none
*/
void rcu_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_AF);
rcu_periph_clock_enable(RCU_SPI0);
rcu_periph_clock_enable(RCU_SPI2);
}
/*!
\brief configure the GPIO peripheral
\param[in] none
\param[out] none
\retval none
*/
void gpio_config(void)
{
/* configure SPI0 GPIO: SCK/PA5, MISO/PA6, MOSI/PA7 */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
}
/*!
\brief configure the SPI peripheral
\param[in] none
\param[out] none
\retval none
*/
void spi_config(void)
{
spi_parameter_struct spi_init_struct;
/* deinitilize SPI and the parameters */
spi_i2s_deinit(SPI0);
spi_i2s_deinit(SPI2);
spi_struct_para_init(&spi_init_struct);
/* configure SPI0 parameter */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.prescale = SPI_PSC_256;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI0, &spi_init_struct);
#if SPI_CRC_ENABLE
/* configure SPI CRC function */
spi_crc_polynomial_set(SPI0, 7);
spi_crc_polynomial_set(SPI2, 7);
spi_crc_on(SPI0);
spi_crc_on(SPI2);
#endif /* enable CRC function */
}
/*!
\brief memory compare function
\param[in] src: source data pointer
\param[in] dst: destination data pointer
\param[in] length: the compare data length
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus memory_compare(uint8_t *src, uint8_t *dst, uint8_t length)
{
while(length--) {
if(*src++ != *dst++) {
return ERROR;
}
}
return SUCCESS;
}
从机代码:
#include "gd32e10x.h"
#include "gd32e10x_eval.h"
//#define SPI_CRC_ENABLE 1
#define ARRAYSIZE 10
uint8_t spi0_send_array[ARRAYSIZE] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
uint8_t spi2_send_array[ARRAYSIZE] = {0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA};
uint8_t spi0_receive_array[ARRAYSIZE];
uint8_t spi2_receive_array[ARRAYSIZE];
uint32_t send_n = 0, receive_n = 0;
uint32_t crc_value1 = 0, crc_value2 = 0;
void rcu_config(void);
void gpio_config(void);
void spi_config(void);
ErrStatus memory_compare(uint8_t *src, uint8_t *dst, uint8_t length);
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* initialize the LEDs */
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
/* enable peripheral clock */
rcu_config();
/* configure GPIO */
gpio_config();
/* configure SPI */
spi_config();
/* enable SPI */
spi_enable(SPI2);
spi_enable(SPI0);
#if SPI_CRC_ENABLE
/* wait for transmit completed */
while(send_n < ARRAYSIZE) {
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI2, spi2_send_array[send_n]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
spi2_receive_array[receive_n] = spi_i2s_data_receive(SPI2);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n++] = spi_i2s_data_receive(SPI0);
}
/* send the last data */
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI2, spi2_send_array[send_n]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
/* send the CRC value */
spi_crc_next(SPI2);
spi_crc_next(SPI0);
/* receive the last data */
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n] = spi_i2s_data_receive(SPI0);
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
spi2_receive_array[receive_n++] = spi_i2s_data_receive(SPI2);
/* receive the CRC value */
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_RBNE)) {
}
crc_value1 = spi_i2s_data_receive(SPI0);
crc_value2 = spi_i2s_data_receive(SPI2);
/* check the CRC error status */
if(SET != spi_i2s_flag_get(SPI0, SPI_FLAG_CRCERR)) {
gd_eval_led_on(LED2);
} else {
gd_eval_led_off(LED2);
}
if(SET != spi_i2s_flag_get(SPI2, SPI_FLAG_CRCERR)) {
gd_eval_led_on(LED3);
} else {
gd_eval_led_off(LED3);
}
#else
/* wait for transmit completed */
while(receive_n < ARRAYSIZE) {
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) {
}
spi_i2s_data_transmit(SPI0, spi0_send_array[send_n++]);
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) {
}
spi0_receive_array[receive_n++] = spi_i2s_data_receive(SPI0);
}
/* compare receive data with send data */
if(ERROR != memory_compare(spi0_receive_array, spi0_send_array, ARRAYSIZE)) {
gd_eval_led_on(LED2);
} else {
gd_eval_led_off(LED2);
}
#endif /* enable CRC function */
while(1) {
}
}
/*!
\brief configure different peripheral clocks
\param[in] none
\param[out] none
\retval none
*/
void rcu_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_AF);
rcu_periph_clock_enable(RCU_SPI0);
rcu_periph_clock_enable(RCU_SPI2);
}
/*!
\brief configure the GPIO peripheral
\param[in] none
\param[out] none
\retval none
*/
void gpio_config(void)
{
/* configure SPI0 GPIO: SCK/PA5, MISO/PA6, MOSI/PA7 */
/* set GPIO PA4 as SPI0 NSS input */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
}
/*!
\brief configure the SPI peripheral
\param[in] none
\param[out] none
\retval none
*/
void spi_config(void)
{
spi_parameter_struct spi_init_struct;
/* deinitilize SPI and the parameters */
spi_i2s_deinit(SPI0);
spi_struct_para_init(&spi_init_struct);
/* configure SPI0 parameter */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_SLAVE;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.nss = SPI_NSS_HARD;
spi_init_struct.prescale = SPI_PSC_256;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI0, &spi_init_struct);
#if SPI_CRC_ENABLE
/* configure SPI CRC function */
spi_crc_polynomial_set(SPI0, 7);
spi_crc_polynomial_set(SPI2, 7);
spi_crc_on(SPI0);
spi_crc_on(SPI2);
#endif /* enable CRC function */
}
/*!
\brief memory compare function
\param[in] src: source data pointer
\param[in] dst: destination data pointer
\param[in] length: the compare data length
\param[out] none
\retval ErrStatus: ERROR or SUCCESS
*/
ErrStatus memory_compare(uint8_t *src, uint8_t *dst, uint8_t length)
{
while(length--) {
if(*src++ != *dst++) {
return ERROR;
}
}
return SUCCESS;
}
传输0x05,更改传输速度8分频,时钟极性1,第二个边沿采样得到如下结果:
传输0x05,更改传输速度64分频,时钟极性1,第二个边沿采样得到如下结果:
A0
1010 0000
0A
0000 1010
更改256分频,时钟极性0,第一个边沿采样得到如下结果:
检查SPI时钟频率是否正确,确保时钟频率在设备允许的范围内;
检查SPI数据传输模式是否正确,确保数据传输模式与设备要求的模式一致;
检查SPI数据位宽是否正确,确保数据位宽与设备要求的位宽一致;
检查SPI片选信号是否正确,确保片选信号与设备要求的信号一致;
检查SPI数据传输顺序是否正确,确保数据传输顺序与设备要求的顺序一致;
检查SPI数据传输时序是否正确,确保数据传输时序与设备要求的时序一致;
检查SPI数据传输方向是否正确,确保数据传输方向与设备要求的方向一致;
检查SPI数据传输格式是否正确,确保数据传输格式与设备要求的格式一致;
检查SPI数据传输时的中断是否正确,确保数据传输时的中断与设备要求的中断一致;
检查SPI数据传输时的延时是否正确,确保数据传输时的延时与设备要求的延时一致。
问题标题: GD32单片机SPI数据传输发生错位
问题内容: 我正在使用两个GD32E103单片机进行SPI数据传输,但是主机和从机接收的数组都会发生移位,并且无法按照数组顺序接收。我作为从机,希望实现以下传输方式: 主机发送数据7F 00 00 00 00 00 00 7F
,从机应该回传数据7F 05 05 05 05 05 05 7F
。如果无法实现以数组形式传输,也可以按照单个数据进行传输。
优化后的问题:
我正在使用两个GD32E103单片机进行SPI数据传输,但是主机和从机接收的数组都会发生移位,并且无法按照数组顺序接收。我作为从机,希望实现以下传输方式: 主机发送数据7F 00 00 00 00 00 00 7F
,从机应该回传数据7F 05 05 05 05 05 05 7F
。请问如何解决这个问题?谢谢!
主机代码示例:
[请提供主机代码]
从机代码示例:
[请提供从机代码]
传输结果1: 14 0001 0100 A0 1010 0000 0A 0000 1010
传输结果2: [请提供传输结果2]
传输结果3: [请提供传输结果3]
尽管数据是正确的,但顺序并不按照发送顺序。我也尝试过使用中断和DMA处理,但问题依然存在。
有没有了解如何解决这个问题的工程师能够提供帮助?谢谢!