OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12409|回复: 7

SPI通信问题

[复制链接]

5

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2011-5-10
在线时间
0 小时
发表于 2011-6-19 13:38:11 | 显示全部楼层 |阅读模式

一块板子上的SPI1为主,另一块板子上的SPI1为从,为什么主SPI不能发送数据,它的SCK、MOSI引脚,用示波器看没有信号,仿真时看到SPI1中的DR寄存器根本写不进数据,,但是奇怪的是,执行发送语句时,BYS寄存器置位(正在发送),执行完发送语句后,TXE置位(发送完毕),但为什么引脚上没有任何信号呢(包括时钟信号SCK)

 void GPIO_Configration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO,ENABLE);

/***********初始化主设备SPI1*********/ 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
 GPIO_Init(GPIOA,&GPIO_InitStructure);

}

 

void SPI_Configration(void)
{
 SPI_InitTypeDef SPI_InitStruct;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 ,ENABLE)

 SPI_I2S_DeInit(SPI1);
 SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx;
 SPI_InitStruct.SPI_Mode = SPI_Mode_Master;//主设备
 SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b;//数据宽度16位
 SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
 SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;//极性和相位
 SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;//NSS为软件模式
 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//分频
 SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
 SPI_InitStruct.SPI_CRCPolynomial = 7;
 SPI_Init(SPI1,&SPI_InitStruct);   //初始化SPI1为主设备 
 SPI_Cmd(SPI1,ENABLE);

}

原子大哥,虽然是用库写的,能帮我看看吗或者哪位帮我看看,就是不发送数据

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-6-20 08:47:10 | 显示全部楼层
int man(void)
{
    GPIO_Configration();
    SPI_Configration();
    while(1)
    {
  while((SPI1->SR&1<<1)==0);//等待发送区空   
SPI1->DR=0XAA;         //发送一个byte 
retry=0;
while((SPI1->SR&1<<0)==0) ;//等待接收完一个byte     
    }
}
主函数改为上面这样,再用示波器看有没有信号.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2011-5-10
在线时间
0 小时
 楼主| 发表于 2011-6-20 10:40:01 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子大哥,我试了还是不行,我的主函数和你基本一样,不过使用库写的
             while(1)
             {
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//发送为空
                        SPI_I2S_SendData(SPI1,0x4);//发送
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待发送结束

GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_ms(1000);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_ms(1000);//LED闪烁
}
我感觉SPI根本没工作,但是我使能了中断,发送完数据,程序还能跳到中断,又说明三SPI是工作的,但就是没信号,是不是GPIO没有配置好啊,看了好多例程就是这么配置啊,不过还是谢谢原子大哥
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-6-20 11:26:47 | 显示全部楼层
回复【3楼】lip0201:

---------------------------------
软件仿真,看看寄存器数据吧.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2011-5-10
在线时间
0 小时
 楼主| 发表于 2011-6-20 13:08:08 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
软件仿真试过,除了发送缓存(DR寄存器)始终没有数据之外,其他寄存器都正常
刚才我把SPI1和SPI2连接之后,程序居然运行成功了,我又用示波器看SPI1的引脚,发现还是没有信号,示波器检测不到信号,而SPI2居然已经接收到了,真实奇怪了
回复 支持 反对

使用道具 举报

5

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2011-5-10
在线时间
0 小时
 楼主| 发表于 2011-6-20 13:14:05 | 显示全部楼层
#include "stm32f10x.h"
#include "delay.h"


static u8 fac_us;
static u16 fac_ms;

void SPI_Configration(void);
void GPIO_Configration(void);
void NVIC_Configuration(void); 
void delay_init(u8 SYSCLK);

int main(void)
{
// u16 send_data = 4;
delay_init(72);
GPIO_Configration();
SPI_Configration();
NVIC_Configuration();


while(1)

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1,0x4);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

GPIO_ResetBits(GPIOA,GPIO_Pin_8);
delay_ms(1000);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_ms(1000); //指示程序在运行
}
}

void SPI_Configration(void)
{
SPI_InitTypeDef SPI_InitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 ,ENABLE); //使能SPI1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE); //使能SPI2时钟

SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //72M 除以4等于18M
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStruct.SPI_CRCPolynomial = 7;
SPI_Init(SPI1,&SPI_InitStruct);   //初始化SPI1为主

SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//36M除以2等于18M
SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;
SPI_Init(SPI2,&SPI_InitStruct);   //初始化SPI2为从

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);  //使能SPI2接受中断

SPI_Cmd(SPI2,ENABLE);//使能SPI2接收
SPI_Cmd(SPI1,ENABLE);//使能SPI1发送

}

void GPIO_Configration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOD,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启复用

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化LED0

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化LED1,用于SPI2接受数据的指示

/***********初始化主设备SPI1*********/
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA,&GPIO_InitStructure); 


/***********初始化从设备SPI2_SCK和SPI2_MOSI*******************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure); 

}



void NVIC_Configuration(void)
{
   NVIC_InitTypeDef NVIC_InitStructure;
 
   
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
   
   
   NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}



//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
fac_us=SYSCLK/8;     
fac_ms=(u16)fac_us*1000;
}     
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864 
void delay_ms(u16 nms)
{        
u32 temp;    
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00;           //清空计数器
SysTick->CTRL=0x01 ;          //开始倒数  
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
SysTick->CTRL=0x00;       //关闭计数器
SysTick->VAL =0X00;       //清空计数器        
}   
//延时nus
//nus为要延时的us数.         
void delay_us(u32 nus)
{
u32 temp;       
SysTick->LOAD=nus*fac_us; //时间加载     
SysTick->VAL=0x00;        //清空计数器
SysTick->CTRL=0x01 ;      //开始倒数   
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
SysTick->CTRL=0x00;       //关闭计数器
SysTick->VAL =0X00;       //清空计数器  
}

/***********************以下是SPI2的中断函数************************************/
void SPI2_IRQHandler(void)
{
u8 status;

if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_RXNE) == SET) //如果SPI2接收到数据
{
if(SPI_I2S_ReceiveData(SPI2) == 0x4)//接收到的是发送的0x4
{
status = GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2);
if(status == Bit_SET)
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
else
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
}
// SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, DISABLE);
}
程序很简单,就是一个小实验,大家一起学习
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-6-20 13:54:13 | 显示全部楼层
回复【5楼】lip0201:
---------------------------------
很明显,你的示波器肯定在使用上存在问题.
乳沟发收成功了,示波器绝对可以看到的.
1,检查示波器是否连接正确.
2,检查示波器设置是否正确.
PS:最好让SPI不停的发,这样很容易抓到波形.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

30

主题

77

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
217
金钱
217
注册时间
2012-11-12
在线时间
0 小时
发表于 2012-12-17 21:49:22 | 显示全部楼层
回复【6楼】lip0201:
---------------------------------
大哥,您能把你发的这个例程发给我吗?谢啦517217451@qq.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-19 09:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表