我已经构建了一个带有STM8L的原型板,我希望它被使用并配置为一个SPI从属程序。我正在用树莓皮做师父来测试它。
为此,我使用ST提供的名为"STM8标准外设库“的库,但文档非常贫乏,不需要花费费用.
我可以在没有问题的情况下从Raspberry Pi发送数据,并在STM8上接收它,但我不能从MISO上的STM8上将任何数据发回给树莓。
有人知道我怎样才能把一些数据发回给Raspberry Pi大师吗?我的错误在哪里?
以下是主要代码:
void main(void)
{
// GPIO
GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
CLK_Config();
// Set the MOSI and SCK at high level
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5, ENABLE);
SPI_DeInit(SPI1);
SPI_Init(SPI1, SPI_FirstBit_LSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_2Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);
SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);
// Enable SPI
SPI_Cmd(SPI1, ENABLE);
/* Infinite loop */
while (1)
{
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// SPI polling
if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
GPIO_ToggleBits(GPIOA, GPIO_Pin_7);
uint8_t data = SPI_ReceiveData(SPI1);
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// I can't send back data here, it doesn't work
SPI_SendData(SPI1, 0xFA);
uint8_t test = SPI1->DR;
GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}
}
}
static void CLK_Config(void)
{
/* Select HSE as system clock source */
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
/*High speed external clock prescaler: 1*/
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
{}
/* Enable SPI clock */
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}和RPi简单代码:
#include <iostream>
#include <wiringPi.h>
#include <wiringPiSPI.h>
using namespace std;
int main()
{
wiringPiSetup();
wiringPiSPISetup(0, 50000);
unsigned char data[] = {0x5A};
wiringPiSPIDataRW(0, data, 2);
std::cout<<data<<std::endl;
return 0;谢谢你的帮助!)
编辑:我认为错误在uC代码中,因为spi数据寄存器仍然包含主读后发送的数据。我不能改变它,即使是试图直接写在登记簿上。
另外:设备只包含一个SPI数据寄存器是正常的吗?如果它没有一个用于MOSI (Rx)和一个用于MISO(Tx),那么它怎么会是全双工呢?我觉得我对SPI有些不理解。我对这个串行协议不是很有经验。我以前主要使用I2C。
发布于 2021-09-27 15:38:09
我终于发现我的错误在哪里。
首先,我忘记在MISO引脚上配置拉拔电阻:
// Set the MOSI and SCK at high level
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);接下来,SPI配置是错误的。Rpi位于MSB中,而在LSB中为STM8,当需要位于第一个边缘时,相位处于第二边缘:
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);最后,这不是一个错误,而是一种不理想的测试方法:我与主机一起发送了0x81,但它是二进制的(0b10000001)。我应该发送一些异步消息,例如0x17 (0b00010111)。
以及完整的STM8代码:
#include "stm8l15x.h"
#include "stm8l15x_it.h" /* SDCC patch: required by SDCC for interrupts */
static void CLK_Config(void);
void Delay(__IO uint16_t nCount);
void main(void)
{
// GPIO
GPIO_Init(GPIOA, GPIO_Pin_7, GPIO_Mode_Out_PP_Low_Fast);
CLK_Config();
// Set the MOSI and SCK at high level (I added MOSI)
GPIO_ExternalPullUpConfig(GPIOB, GPIO_Pin_6 | GPIO_Pin_5 | GPIO_Pin_7, ENABLE);
SPI_DeInit(SPI1);
SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Slave,
SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_Direction_2Lines_FullDuplex,
SPI_NSS_Hard, (uint8_t)0x07);
SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);
// Enable SPI
SPI_Cmd(SPI1, ENABLE);
/* Infinite loop */
while (1)
{
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY));
// SPI polling
if(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == SET) {
// maybe this line is not necessary, I didn't have the time to test without it yet
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY);
uint8_t data = SPI_ReceiveData(SPI1);
while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE));
if(data==0x82) SPI_SendData(SPI1, 0xCD);
GPIO_ResetBits(GPIOA, GPIO_Pin_7);
}
}
}
/* Private functions ---------------------------------------------------------*/
static void CLK_Config(void)
{
/* Select HSE as system clock source */
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
/*High speed external clock prescaler: 1*/
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_2);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI)
{}
/* Enable SPI clock */
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
}
void Delay(__IO uint16_t nCount)
{
/* Decrement nCount value */
while (nCount != 0)
{
nCount--;
}
}
/*******************************************************************************/
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* Infinite loop */
while (1)
{
}
}
#endifPS:
我在linux上,软件工具不适合我的操作系统,所以我使用了一些工具来进行开发。我认为它对某些人是有用的,所以我在这里补充如下:
首先,lib无法用SDCC编译,所以我使用了我在这里找到的修补程序:https://github.com/gicking/STM8-SPL_SDCC_patch
要上传到uC,我使用stm8flash和ST链接V2:https://github.com/vdudouyt/stm8flash。
我也遇到了一些困难,无法找到STM8L的库。这里是:https://www.st.com/en/embedded-software/stsw-stm8016.html
PS2:
我知道要回答与硬件有关的问题并不容易。有没有人知道有哪些网站对这类问题有更详细的说明?
发布于 2021-09-26 17:05:01
SPI要求主程序提供时钟。如果您希望从服务器发送什么--您的主必须发送一些虚拟数据来为从服务器生成时钟。
https://stackoverflow.com/questions/69337091
复制相似问题