对于两块STM32通过SPI通讯,在网上看到有资料说是有bug缺陷,具体什么缺陷我不太清楚,前段时间我在做这方面项目,也发帖咨询过不少人,经过一个多星期测试,总算可以通讯成功,而且通讯数据不会出错了。
废话不说进入正题:
我们要实现SPI主从通讯一定要用片选(具体怎么用下面有介绍),而且两块开发板一定要共地,不然就呵呵了,我也不知道原因。我们从主机开始:
SPI初始化函数:
[mw_shl_code=c,true]void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTB时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );//SPI1时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PB13/14/15上拉
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_3);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //定义波特率预分频的值:波特率预分频值为4
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始,高位在前
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
// SPI1_ReadWriteByte(0xff);//启动传输,这句一定去掉,加了会错位
} [/mw_shl_code]
其实吃实话大家都差不多,下面是收发函数:跟原子哥的一样,我就不说了,
我们主要来看主函数:
[mw_shl_code=c,true]int main(void)
{
u16 i=0,number=0;
u8 datatemp[SIZE];
u32 FLASH_SIZE;
u8 rx=0;
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为9600
LED_Init(); //LED端口初始化
LCD_Init();
KEY_Init();
SPI1_Init();
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(60,50,200,16,16,"WarShip STM32");
LCD_ShowString(60,70,200,16,16,"SPI TEST");
LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(60,110,200,16,16,"2012/9/11");
LCD_ShowString(60,130,200,16,16,"LoopBack Mode");
LCD_ShowString(60,150,200,16,16,"KEY0:Send WK_UP:Mode");//显示提示信息
LCD_ShowString(60,170,200,16,16,"Count:"); //显示当前计数值
LCD_ShowString(60,190,200,16,16,"Send Data:"); //提示发送的数据
LCD_ShowString(60,250,200,16,16,"Receive Data:"); //提示接收到的数据
while(1) //检测不到W25Q64
{
number=KEY_Scan(0);
if(number==1)
{ LED1=0;
while(1)
{ for(key=0;key<9;key++)
{ GPIO_ResetBits(GPIOA,GPIO_Pin_3);
rx=SPI1_ReadWriteByte(key);
GPIO_SetBits(GPIOA,GPIO_Pin_3);
LCD_ShowxNum(60+2*32,210,rx,3,16,0X80);
delay_ms(1000);
}
}
}
}
}[/mw_shl_code]
我主要解释第一个while(1)循环里面的函数,首先我们加一个按键:
[mw_shl_code=c,true]number=KEY_Scan(0);当按键按下时,我们进入SPI发送程序,其中LED1用来显示程序进去了,[/mw_shl_code]
[mw_shl_code=c,true]在发送函数里面,我们的SPI主机依次发送0-8的数据,一秒发送一次,不断循环发送,现在大家看下[/mw_shl_code]
[mw_shl_code=c,true]第二个while(1)循环,是不是有个
[mw_shl_code=c,true]GPIO_ResetBits(GPIOA,GPIO_Pin_3);这是我用来做片选的,当我们要进入发送的时候,首先通过这个片选[/mw_shl_code]
[mw_shl_code=c,true]告诉我们的从机我要开始发送了,然后发送,发送完后拉高,不断这样发送,这个[/mw_shl_code]
[mw_shl_code=c,true]
[mw_shl_code=c,true]LCD_ShowxNum(60+2*32,210,rx,3,16,0X80);[/mw_shl_code]
用来显示主机收的从机发送的数据,主机大概就这样[/mw_shl_code]
[mw_shl_code=c,true]现在大家看看从机的主函数:[/mw_shl_code]
[mw_shl_code=c,true]
[mw_shl_code=c,true] while(1) //检测不到W25Q64
{
number=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3);
if(!number)
{
key = SPI2_ReadWriteByte(++tx);
LCD_ShowxNum(60+2*32,210,key,3,16,0X80);
}
}[/mw_shl_code]
用一个number来读取片选信号,当片选选中时,就进去执行
[/mw_shl_code]
[mw_shl_code=c,true]
[mw_shl_code=c,true] key = SPI2_ReadWriteByte(++tx);同时发送数据给主机,[/mw_shl_code]
[mw_shl_code=c,true]这样就可以正确的通讯了,大家注意当给两块板烧完程序后要先开主机,是主机,主机重要的说三遍[/mw_shl_code]
[mw_shl_code=c,true]然后开从机,最后按下主机开始按钮,就是那个key(0),就可以开始通讯,然后大家可以根据自己的需求改,大家有啥好的想法请大家提出来,这个是初级版本,在随后我会继续发布,看能不能改进下代码。[/mw_shl_code]
[mw_shl_code=c,true]这是我上传的包,keil4的,欢迎大家测试。[/mw_shl_code]
[/mw_shl_code]
[/mw_shl_code]
|