关于DSP24049C与STM32F103C8T6之间的SPI通讯记录
所用材料:
STM32F103C8T6(最小系统板)
DSPF280049C
VOFA+ (串口调试助手)
背景介绍:
DSP作为主设备,STM32作为从设备。目前仅要求主设备向从设备发送数据能够被接收并且通过STM32的串口打印至上位机即可。
第一步:DSP280049C的SPI配置
void SPIA_int (void)
{
//GPIO配置
// SPISOMIB.
//
GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 1);
GPIO_SetupPinOptions(17, GPIO_PULLUP, GPIO_ASYNC);
//
// SPISIMOB clock pin.
//
GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 1);
GPIO_SetupPinOptions(16, GPIO_PULLUP, GPIO_ASYNC);
//
// SPICLKB.
//
GPIO_SetupPinMux(9, GPIO_MUX_CPU1, 7);
GPIO_SetupPinOptions(9, GPIO_PULLUP, GPIO_ASYNC);
//
// SPICSB.
//
GPIO_SetupPinMux(33, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(33, GPIO_OUTPUT, GPIO_ASYNC);
GPIO_WritePin(33, 1);
//SPI配置
// Set reset low before configuration changes
// Clock polarity (0 == rising, 1 == falling)
// 16-bit character
// Disable loop-back
//
SpiaRegs.SPICCR.bit.SPISWRESET = 0;
SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;
SpiaRegs.SPICCR.bit.SPICHAR = (16 - 1);
SpiaRegs.SPICCR.bit.SPILBK = 0;
//
// Enable master (0 == slave, 1 == master)
// Enable transmission (Talk)
// Clock phase (0 == normal, 1 == delayed)
// SPI interrupts are disabled
//
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;
SpiaRegs.SPICTL.bit.TALK = 1;
SpiaRegs.SPICTL.bit.CLK_PHASE = 0;
SpiaRegs.SPICTL.bit.SPIINTENA = 0;
//
// Set the baud rate using a 2 MHz SPICLK
// BRR = (LSPCLK / SPICLK) - 1
//
SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = ((25000000 / 2000000) - 1);
//
// Set FREE bit
// Halting on a breakpoint will not halt the SPI
//
SpiaRegs.SPIPRI.bit.FREE = 1;
//
// Release the SPI from reset
//
SpiaRegs.SPICCR.bit.SPISWRESET = 1;
}
uint16_t SPIA_sendone(uint16_t txdata)
{
uint16_t rxdata;
GPIO_WritePin(33, 0);
SpiaRegs.SPITXBUF = txdata;
while (!SpiaRegs.SPISTS.bit.INT_FLAG){}
GPIO_WritePin(33, 1);
rxdata = SpiaRegs.SPIRXBUF;
return rxdata;
}
然后是在主程序中进行定时发送的:
void main(void)
{
InitSysCtrl();
DINT;
InitPieCtrl();
IER=0x0000;
IFR=0x0000;
InitPieVectTable();
DELAY_US(1000L);
LED_int();
SPIA_int ();
TIM0_int ();
SCIA_int();
ADC_int();
QEP_int();
//EPWM1_int();
EINT; //使能全局中断
ERTM;
while (1)
{
rData = SPIA_sendone(12345);
DELAY_US(200L);
}
}
第二步:STM32基于HAL库的SPI配置
从设备端我开启了SPI接收中断,在CUBEMX配置之后只需要添加一下程序。
在spi.c中添加如下:
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
HAL_SPI_Receive_IT(&hspi1,&rdata, 1);//添加部分
/* USER CODE END SPI1_Init 2 */
}
然后在中断函数中进行接收:找到**stm32f1xx_it.c**中的
void SPI1_IRQHandler(void)
{
/* USER CODE BEGIN SPI1_IRQn 0 */
uint8_t rdata;
uint16_t rxdata;
/* USER CODE END SPI1_IRQn 0 */
HAL_SPI_IRQHandler(&hspi1);
/* USER CODE BEGIN SPI1_IRQn 1 */
HAL_SPI_Receive_IT(&hspi1,&rdata, 1);
rxdata = *(&rdata) + *(&rdata+1)*256;
printf ("%d\r\n",rxdata);
/* USER CODE END SPI1_IRQn 1 */
}
配置STM32的具体步骤不在此细讲了,观众们看到这里就结束了,接来下是个人学习记录部分了。
碰到的问题记录:
由于主设备DSP所需要发送的数据是大于256的,所以需要定义一个Uint16_t型的数据,同时DSP的SPI也设置为了16bit为一字节发送。
但是这里存在一个问题就是,STM32作为从设备,接收数据时的数据类型只能是Uint8_t,也就是说STM32在接收数据(假设发送的数据为:12345
)后,会将数据拆分为两个8bit的字节,分别存储在&rdata与&(rdata+1)
两个相邻的地址中。
因此想到了这一步:在未来的其他通讯方式中也能够借鉴使用
rxdata = *(&rdata) + *(&rdata+1)*256;
截止2023/7/3 关于DSP280049C与STM32F103C8T6的SPI通讯改进
改进目标:为了满足DSP能够在200us时间内,发送两个数据至STM32并且STM32能够通过串口打印到上位机串口软件VOFA+
DSP280049C的SPI主机配置
void SPIA_int (void)
{
//GPIO配置
// SPISOMIB.
//
GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 1);
GPIO_SetupPinOptions(17, GPIO_PULLUP, GPIO_ASYNC);
//
// SPISIMOB clock pin.
//
GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 1);
GPIO_SetupPinOptions(16, GPIO_PULLUP, GPIO_ASYNC);
//
// SPICLKB.
//
GPIO_SetupPinMux(9, GPIO_MUX_CPU1, 7);
GPIO_SetupPinOptions(9, GPIO_PULLUP, GPIO_ASYNC);
//
// SPICSB.
//
GPIO_SetupPinMux(33, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(33, GPIO_OUTPUT, GPIO_ASYNC);
GPIO_WritePin(33, 1);
//SPI配置
// Set reset low before configuration changes
// Clock polarity (0 == rising, 1 == falling)
// 16-bit character
// Enable loop-back
//
SpiaRegs.SPICCR.bit.SPISWRESET = 0;
SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;
SpiaRegs.SPICCR.bit.SPICHAR = (8 - 1);
SpiaRegs.SPICCR.bit.SPILBK = 0;
//
// Enable master (0 == slave, 1 == master)
// Enable transmission (Talk)
// Clock phase (0 == normal, 1 == delayed)
// SPI interrupts are disabled
//
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;
SpiaRegs.SPICTL.bit.TALK = 1;
SpiaRegs.SPICTL.bit.CLK_PHASE = 0;
SpiaRegs.SPICTL.bit.SPIINTENA = 0;
//
// Set the baud rate using a 2 MHz SPICLK
// BRR = (LSPCLK / SPICLK) - 1
//
SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = ((25000000 / 1000000) - 1);
//
// Set FREE bit
// Halting on a breakpoint will not halt the SPI
//
SpiaRegs.SPIPRI.bit.FREE = 1;
//
// Release the SPI from reset
//
SpiaRegs.SPICCR.bit.SPISWRESET = 1;
}
void SPISendData(uint8_t *data, unsigned int len)
{
int i;
uint16_t rxdata;
GPIO_WritePin(33, 0);
for (i = 0; i < len; i++)
{
// 写入数据到SPI缓冲区
SpiaRegs.SPITXBUF = data[i]<<8;
// 等待数据发送完成
while (SpiaRegs.SPISTS.bit.INT_FLAG != 1);
rxdata = SpiaRegs.SPIRXBUF;
}
GPIO_WritePin(33, 1);
}
uint16_t SPIA_sendtwo(uint16_t txdata1,uint16_t txdata2)
{
uint8_t data[6];
data[0] = 1;
data[5] = 255;
data[1] = txdata1/256;
data[2] = txdata1%256;
data[3] = txdata2/256;
data[4] = txdata2%256;
SPISendData(data, 6);
}
STM32的SPI从机配置(轮询接收)
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
//main函数轮询接收
while (1)
{
HAL_SPI_TransmitReceive(&hspi1,Txdata,Rxdata,6,0xffff);
if (Rxdata[0]==1 && Rxdata[5]==255)
{
data1 = Rxdata[1]*256+Rxdata[2];
data2 = Rxdata[3]*256+Rxdata[4];
Sendtwodata(data1,data2);
}
else
{
MX_SPI1_Init();
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
//串口发送函数
void Sendtwodata(uint16_t data0,uint16_t data1)
{
uint8_t indata0=44;
uint8_t indata1=10;
uint8_t indata2=13;
uint8_t cdata[8];
cdata[0] = (data0/1000)+48;
cdata[1] = ((data0%1000)/100)+48;
cdata[2] = ((data0%100)/10)+48;
cdata[3] = ((data0%10))+48;
cdata[4] = (data1/1000)+48;
cdata[5] = ((data1%1000)/100)+48;
cdata[6] = ((data1%100)/10)+48;
cdata[7] = ((data1%10))+48;
HAL_UART_Transmit(&huart1, &cdata[0], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[1], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[2], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[3], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &indata0, 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[4], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[5], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[6], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &cdata[7], 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &indata2, 1, 10);//HAL库串口发送函数
HAL_UART_Transmit(&huart1, &indata1, 1, 10);//HAL库串口发送函数
}