STM32F030的硬件SPI从模式,从机应答时丢失首个字节?
如题,主机发送{0,0,0,0},想要得到的从机应答{0x00,0x70,0x53,0xb0};实际获取的应答为{0x70,0x53,0xb0,0x00}。中断程序如下:
uint32_t spi_TxBuff = 0x00000000;
uint32_t DataRegs;
#define OFFSET_0 24
uint8_t offsetbits = OFFSET_0;
uint8_t rw_Flag;//0x00:read,0x80:write,=data & 0x80;
uint8_t reg_Address;//=data & 0x7F;
void SPI2_IRQHandler(void)
{
uint8_t data;
if (SPI2->SR & 0x1)
{
data = SPI_ReceiveData8(SPI2);
rw_Flag = data & 0x80;
reg_Address = data & 0x7F;
if (rw_Flag != 0x00)
{
//write to regs
//SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
}
else
{
//read from regs
if (reg_Address < 10)
{
if (offsetbits == OFFSET_0)
{
spi_TxBuff = DataRegs;
}
}
else
{
spi_TxBuff = 0x00FFFFFF;
}
}
}
if (SPI2->SR & 0x2)
{
SPI_SendData8(SPI2, (0xFF & (spi_TxBuff >> offsetbits)));
if (offsetbits >= 8)
{
offsetbits -= 8;
}
else
{
offsetbits = OFFSET_0;
}
}
}
void EXTI4_15_IRQHandler(void)
{
EXTI->PR ^= (uint16_t)~EXTI_Line11;
offsetbits = OFFSET_0;
}
本帖最后由 Dylan疾风闪电 于 2015-1-5 20:44 编辑
SPI的主/从的初始化代码:
void connectSPI1ToExt(uint16_t BaudRatePCLKDiv, uint16_t CPOL, uint16_t CPHA_Edge)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDefSPI_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
//SPIx_SCK 主模式 推挽复用输出
//SPIx_MOSI 全双工模式/主模式 推挽复用输出
//SPIx_MISO 全双工模式/主模式 浮空输入或带上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_CLK);
GPIO_Init(SPLIT_DEFINE_PORT(X2_CLK), &GPIO_InitStructure);
SetAF_SPI1_SCK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_SDI);
GPIO_Init(SPLIT_DEFINE_PORT(X2_SDI), &GPIO_InitStructure);
SetAF_SPI1_MOSI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X2_SDO);
GPIO_Init(SPLIT_DEFINE_PORT(X2_SDO), &GPIO_InitStructure);
SetAF_SPI1_MISO;
//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = CPOL;
SPI_InitStructure.SPI_CPHA = CPHA_Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = BaudRatePCLKDiv;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_CalculateCRC(SPI1,DISABLE);
SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);
SPI_Cmd(SPI1, ENABLE);
}
void connectSPI2SlaveToExt(uint16_t BaudRatePCLKDiv, uint16_t CPOL, uint16_t CPHA_Edge)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
//SPIx_SCK 从模式 浮空输入
//SPIx_MOSI 全双工模式/从模式 浮空输入或带上拉输入
//SPIx_MISO 全双工模式/从模式 推挽复用输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_CLK_S);
GPIO_Init(SPLIT_DEFINE_PORT(X3_CLK_S), &GPIO_InitStructure);
SetAF_SPI2_SCK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_SDI_S);
GPIO_Init(SPLIT_DEFINE_PORT(X3_SDI_S), &GPIO_InitStructure);
SetAF_SPI2_MOSI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_SDO_S);
GPIO_Init(SPLIT_DEFINE_PORT(X3_SDO_S), &GPIO_InitStructure);
SetAF_SPI2_MISO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = SPLIT_DEFINE_PIN(X3_CS_S);
GPIO_Init(SPLIT_DEFINE_PORT(X3_CS_S), &GPIO_InitStructure);
SetAF_SPI2_NSS;
//寄存器操作
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
/*---------------------------- SPIx CR1 Configuration ------------------------
*
* BIDIMode(双向数据模式使能) = 0 :选择2线的单向数据模式(1:选择单线双向数据模式)。
* BIDIOE(双向模式输出使能) = 0 :输出禁止,只收模式(1:输出使能,只发模式)。
* *注* BIDIOE和BIDIMode决定了通讯的“双线单向模式”、“单线双向模式”和“单线单向模式”。
* CRCEN(硬件CRC使能) = 0 :禁用CRC计算(1:CRC计算使能)。
* CRCNEXT(下一个发送CRC) = 0 :下个发送的值来自发送缓冲器(1:下个发送的值来自CRC寄存器).
* CRCL(CRC的数据长度) = x (0:8位CRC长度)(1:16位CRC长度).
* RxONLY = 0 :全双工(1:只收模式)。
* SSM(软件从机管理) = 0 :禁止软件从设备管理(1:启用软件从设备管理,NSS引脚的电平由SSI位决定)。
* SSI(内部从设备选择) = x 决定了NSS引脚的电平。
* LSBFirst(帧格式) = 0 :先发送MSB(1:先发送LSB)。
* SPE(SPI使能) = 0 :禁止SPI设备(1:开启SPI设备)。
* BR(波特率控制) = value (通信速率为{fPCLK/(2^})。
* MSTR(主设备选择) = 0 :配置为从设备(1:配置为主设备)。
* CPOL(时钟极性) = value (0:空闲状态下SCK保持低电平)(1:空闲状态SCK保持高电平)。
* CPHA(时钟相位) = value (0:第一个时钟边沿开始数据采样)(1:第二个时钟边沿开始数据采样)。
*---------------------------------------------------------------------------*/
SPI2->CR1 &= 0x0000;
SPI2->CR1 |= (uint16_t)(BaudRatePCLKDiv | CPOL | CPHA_Edge);
/*---------------------------- SPIx CR2 Configuration ------------------------
*
* DS(数据长度) = 0111b :8位(0011b~1111b:4位~16位数据长度)。
*---------------------------------------------------------------------------*/
SPI2->CR2 &= 0xF0FF;
SPI2->CR2 |= 0x0700;
/*---------------------------- SPIx CRCPOLY Configuration --------------------
*
* CRCPOLY(数据长度) = 0x0007 :默认的复位值是0x0007。(复位过后可忽略)
*---------------------------------------------------------------------------*/
//SPI2->CRCPR = 0x0007;
/*---------------------------- Activate the SPI mode -------------------------
*
* I2SMODE(I2S模式选择) = 0 :选择SPI模式(选择I2S模式)。
*---------------------------------------------------------------------------*/
SPI2->I2SCFGR &= 0xF7FF;
SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
SPI_Cmd(SPI2, ENABLE);
}
主循环部分代码:
uint8_t temp;
......
int main()
{
NVIC_InitTypeDef NVIC_InitStructure;
......
connectSPI1ToExt(SPI_BaudRatePrescaler_32, SPI_CPOL_Low, SPI_CPHA_1Edge);
connectSPI2SlaveToExt(SPI_BaudRatePrescaler_32, SPI_CPOL_Low, SPI_CPHA_1Edge);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
//Interrupts
NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
while(1)
{
DELAY_MS(500);
SPI1_SS_Low;
DELAY_MS(10);
for(int i=0; i<4; i++)
{
temp = 0;
while (!(SPI1->SR & 0x2));
SPI_SendData8(SPI1, 0x00);
while (!(SPI1->SR & 0x1));
temp = SPI_ReceiveData8(SPI1);
}
DELAY_MS(10);
SPI1_SS_High;;
DELAY_MS(500);
}
} 请各位帮忙看一下,中断处理函数是不是存在什么问题?
因为从设备启用了硬件NSS,所以在片选为高的情况下,硬件应答是0xFF;同时在片选上升沿通过EXTI中断复位偏移量(offsetbits)。
----------------------------------------------------------------------------------------------------
收到数据0x00后,依次发送spi_TxBuff的【31:24】【23:16】【15:8】【7:0】。:) 自己顶一下,哪位高工来看一下,这个问题怎么解决? :)这个问题怎么解决? 6874577 发表于 2015-1-13 12:48
这个问题怎么解决?
我就是想知道啊!不知道程序哪边有问题,重点怀疑是中断函数中的处理机制。 在SPI发送中加断点,看一下发送的时候的spi_TxBuff数据是多少,另外看一下offsetbits值是多少。 spi_TxBuff=0x007053b0;
offsetbits = 24; 从机应答丢失首字节,你试试从机响应的首字节加点延迟。
页:
[1]
2