打印

香版主请进-关于GPIO高速通讯问题

[复制链接]
3092|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
电气罗凯瀚|  楼主 | 2012-4-15 18:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
小弟编程遇到点麻烦,请香版主和各位高工请教。
我最近在编辑SPI的通讯程序,由于传输时钟的速度要高于20M。所以我选用了STM32F107VC。根据ST的资料和性能,时钟可以达到72M,IO的速度可以达到50M。
我在编译的时候设置了内部和外部时钟,实际编译时候只用了一种方式。
当我烧写入芯片迫不及待的想看波形时,发现最快才2M。为了保证我设置频率是正确的。我专门让时钟在MOC输出(PA8)。发现时钟是预计的72M。
为了弄清情况,我专门设置了一个IO使其正反置位。
GPIO_ResetBits(GPIOB, GPIO_Pin_11);
delay(1);
GPIO_SetBits(GPIOB, GPIO_Pin_11);
delay(1);
但是一切不如人愿啊。我在步进行是发现在stm32f10x_gpio.c的265行函数,是不是它有影响,望香版主和各位高工指点。
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
  /* Reset GPIO init structure parameters values */
  GPIO_InitStruct->GPIO_Pin  = GPIO_Pin_All;
  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING;
}
现在就想知道,是时钟设置上面有问题,还是IO置位函数有问题。希望各位指点。
IO定义如下:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_11
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
内部和外部时钟设置如下。
//配置系统外部时钟,使能各外设
void RCC_Configuration(void)                     //时钟初始化
{
    ErrorStatus HSEStartUpStatus;                 //等待时钟的稳定
    RCC_DeInit();                                 //时钟管理重置
    RCC_HSEConfig(RCC_HSE_ON);                //打开外部晶振
    HSEStartUpStatus = RCC_WaitForHSEStartUp();   //等待外部晶振就绪
         if (HSEStartUpStatus == SUCCESS)
         {
            FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  //flash缓冲读取加速
            FLASH_SetLatency(FLASH_Latency_2);        // flash操作的延时
            RCC_HCLKConfig(RCC_SYSCLK_Div1);          //AHB使用系统时钟(只有目标时钟源就绪时时钟切换才会发生 )
            RCC_PCLK2Config(RCC_HCLK_Div2);           //APB2(高速)为HCLK的一半
            RCC_PCLK1Config(RCC_HCLK_Div2);           //APB1(低速)为HCLK的一半
              //注:AHB主要负责外部存储器时钟。PB2负责AD,I/O,高级TIM,串口1,EXTI。
              // APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM,IWDG,WWDG。
            RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //9为时钟倍频系数,PLLCLK = 8MHz * 9 = 72 MHz
              //HSI时钟信号由内部的8MHz的RC振荡器产生,可直接作为系统时钟,或在2分频后作为PLL输入
            RCC_PLLCmd(ENABLE);                       //启动PLL
             while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY==RESET)) {}    //等待PLL启动
            RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);              //将PLL设置为系统时钟源
             while(RCC_GetSYSCLKSource()!=0x08){}                                                      
         }  
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA
                           |RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
                           |RCC_APB2Periph_GPIOD | RCC_APB2Periph_ADC1
                           | RCC_APB2Periph_AFIO |
                           RCC_APB2Periph_SPI1, ENABLE );
  // RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL ,ENABLE );
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4
                           |RCC_APB1Periph_USART3|RCC_APB1Periph_TIM2                           
                           , ENABLE );
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}

//配置系统内部时钟,使能各外设
void RCC_Configuration(void)
{
SystemInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA
                           |RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
                           |RCC_APB2Periph_GPIOD | RCC_APB2Periph_ADC1
                           | RCC_APB2Periph_AFIO |
                           RCC_APB2Periph_SPI1, ENABLE );
  // RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL ,ENABLE );
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4
                           |RCC_APB1Periph_USART3|RCC_APB1Periph_TIM2                           
                           , ENABLE );
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
沙发
电气罗凯瀚|  楼主 | 2012-4-15 18:17 | 只看该作者
香版主不在哇。先自己顶上。

使用特权

评论回复
板凳
电气罗凯瀚|  楼主 | 2012-4-15 18:23 | 只看该作者
哪位高工指点一下小弟哇。

使用特权

评论回复
地板
javenreal| | 2012-4-15 21:12 | 只看该作者
GPIO_ResetBits(GPIOB, GPIO_Pin_11);
delay(1);
GPIO_SetBits(GPIOB, GPIO_Pin_11);
delay(1);

你加了delay,肯定会慢呀。不要delay,用最有效率的指令,据说IO翻转可以达到18M。

另外SPI也不能达到50M吧,我记得最高速率是18M或36M,具体请差手册。

使用特权

评论回复
5
电气罗凯瀚|  楼主 | 2012-4-15 22:29 | 只看该作者
谢谢哈。我调试的时候屏蔽了延时,这里没表达清楚。不好意思哈。
还有是不是这种翻转的方式是错误的呢(在高速翻转的情况下)。
你说的SPI最高就是18M。我就想能有14M就可以了.
现在还在调试中。

使用特权

评论回复
6
westmas| | 2012-4-16 10:32 | 只看该作者
不用库函数,直接写寄存器才能到18M

使用特权

评论回复
7
lut1lut| | 2012-4-16 12:08 | 只看该作者
STM32F107:

USART1通信速度可高达4.5Mb/s
SPI最高时钟速率可达18Mb/s
GPIO翻转速率最高18MHz

这些数据的概念,LZ不要搞混了哦。

使用特权

评论回复
8
来与君| | 2012-4-16 15:50 | 只看该作者
使用了硬件SPI吗?

使用特权

评论回复
9
nongfuxu| | 2012-4-16 17:36 | 只看该作者
我最近在编辑SPI的通讯程序,由于传输时钟的速度要高于20M

LZ把STM32当什么了?

使用特权

评论回复
10
电气罗凯瀚|  楼主 | 2012-4-20 16:04 | 只看该作者
郁闷惨了,调试了N天现在GPIO的翻转最高才7M。
给大家共享一下吧。有高手指点一二。
#include <stm32f10x.h>
#include "stm32f10x_conf.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_usart.h"



#define FLASH_Latency_2                ((uint32_t)0x00000002)  /* FLASH Two Latency cycles */
#define FLASH_PrefetchBuffer_Enable    ((uint32_t)0x00000010)  /* FLASH Prefetch Buffer Enable */
#define RCC_PLLSource_HSE_Div1         ((uint32_t)0x00010000)
//#define RCC_PLLMul_2                    ((uint32_t)0x00000000)
//#define RCC_PLLMul_3                    ((uint32_t)0x00040000)
//#define RCC_PLLMul_4                    ((uint32_t)0x00080000)
//#define RCC_PLLMul_5                    ((uint32_t)0x000C0000)
//#define RCC_PLLMul_6                    ((uint32_t)0x00100000)
//#define RCC_PLLMul_7                    ((uint32_t)0x00140000)
//#define RCC_PLLMul_8                    ((uint32_t)0x00180000)
#define RCC_PLLMul_9                    ((uint32_t)0x001C0000)
//#define RCC_PLLMul_10                   ((uint32_t)0x00200000)
//#define RCC_PLLMul_11                   ((uint32_t)0x00240000)
//#define RCC_PLLMul_12                   ((uint32_t)0x00280000)
//#define RCC_PLLMul_13                   ((uint32_t)0x002C0000)
//#define RCC_PLLMul_14                   ((uint32_t)0x00300000)
//#define RCC_PLLMul_15                   ((uint32_t)0x00340000)
//#define RCC_PLLMul_16                   ((uint32_t)0x00380000)


//时钟初始化
void RCC_Configuration(void)                     //时钟初始化
{
    ErrorStatus HSEStartUpStatus;                 //等待时钟的稳定
    RCC_DeInit();                                 //时钟管理重置
    RCC_HSEConfig(RCC_HSE_ON);                //打开外部晶振
    HSEStartUpStatus = RCC_WaitForHSEStartUp();   //等待外部晶振就绪
         if (HSEStartUpStatus == SUCCESS)
         {
            FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  //flash缓冲读取加速
            FLASH_SetLatency(FLASH_Latency_2);        // flash操作的延时
            RCC_HCLKConfig(RCC_SYSCLK_Div1);          //AHB使用系统时钟(只有目标时钟源就绪时时钟切换才会发生 )
            RCC_PCLK2Config(RCC_HCLK_Div1);           //APB2(高速)为HCLK的一半
            RCC_PCLK1Config(RCC_HCLK_Div1);           //APB1(低速)为HCLK的一半
              //注:AHB主要负责外部存储器时钟。PB2负责AD,I/O,高级TIM,串口1,EXTI。
              // APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM,IWDG,WWDG。
            RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //9为时钟倍频系数,PLLCLK = 8MHz * 9 = 72 MHz
              //HSI时钟信号由内部的8MHz的RC振荡器产生,可直接作为系统时钟,或在2分频后作为PLL输入
            RCC_PLLCmd(ENABLE);                       //启动PLL
             while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY==RESET)) {}    //等待PLL启动
            RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);              //将PLL设置为系统时钟源
             while(RCC_GetSYSCLKSource()!=0x08){}                                                      
         }  
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA
                           |RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
                           |RCC_APB2Periph_GPIOD | RCC_APB2Periph_ADC1
                           | RCC_APB2Periph_AFIO |
                           RCC_APB2Periph_SPI1, ENABLE );
  // RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL ,ENABLE );
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4
                           |RCC_APB1Periph_USART3|RCC_APB1Periph_TIM2                                  
                           , ENABLE );
         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

}
/*
//配置系统时钟,使能各外设时钟
void RCC_Configuration(void)
{
        SystemInit();       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA
                           |RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
                           |RCC_APB2Periph_GPIOD | RCC_APB2Periph_ADC1
                           | RCC_APB2Periph_AFIO |
                           RCC_APB2Periph_SPI1, ENABLE );
  // RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL ,ENABLE );
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4
                           |RCC_APB1Periph_USART3|RCC_APB1Periph_TIM2                                  
                           , ENABLE );
         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}

*/

void GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}

int main(void)
{  
        RCC_Configuration();
        GPIO_config();

        while (1)
        {
//      GPIOB->BRR=GPIO_Pin_11;
//      GPIOB->BSRR=GPIO_Pin_11;
    GPIOA->BRR=0x00000001;
    GPIOA->BSRR=0x00000001;
        }
}

使用特权

评论回复
11
香水城| | 2012-4-21 11:36 | 只看该作者
搞不懂LZ是怎么想的,你要做SPI的通讯程序,为什么要研究GPIO的翻转?为什么不直接使用SPI模块?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

21

帖子

0

粉丝