这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » (NRF24L01驱动成功)hanshuyujifen2的 ARM DIY进程贴

共119条 6/12 |‹ 4 5 6 7 8 9 ›| 跳转至
高工
2012-04-15 21:30:39     打赏
51楼
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.5pt;"Calibri","sans-serif"; mso-bidi-"Times New Roman";} 使用库里的模板,外接12MHz晶振的设置方法 遇见的问题: 串口芯片搞定了,想使用ST库模板,进行串口通信实验。遇见问题:配置好串口之后,发送数据,由于晶振频率设置的不正确,接收到的数据全是乱码。 库模板里边,是针对内部8MHz晶振设置系统时钟的。系统启动之后,自动设置使用内部8MHZ晶振。因此要使用外部晶振需要对模板进行一些修改。一下是我今天修改模板以使用12M晶振的过程。   首先,main函数最前面的一段文字:

 /*!< At this stage the microcontroller clock setting is already configured,

       this is done through SystemInit() function which is called from startup

       file (startup_stm32f10x_xx.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f10x.c file

     */

系统在进入Main函数之前,已经配置好了系统时钟。即在启动文件startup_stm32f10x_hd_vl.s里边,已经调用SystemInit()设置了系统时钟。 找到SystemInit函数,定义如下(代码过长,根据预定义(STM32F10X_HD_VL)删除了不必要的): void SystemInit (void) {  

 /* Reset the RCC clock configuration to the default reset state(for debug purpose) */

 /* Set HSION bit 开启内部8MHz振荡器 */

 RCC->CR |= (uint32_t)0x00000001;  

 /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

 RCC->CFGR &= (uint32_t)0xF0FF0000;//0xF0FF0000;       

 /* Reset HSEON, CSSON and PLLON bits */

 RCC->CR &= (uint32_t)0xFEF6FFFF;  

 /* Reset HSEBYP bit */

//位(16)0:HSEON,关闭外部高速时钟HSE
 //位(19)0:CSSON,关闭时钟安全系统CSS
 //位(24)0:PLLON,关闭PLL

 RCC->CR &= (uint32_t)0xFFFBFFFF;  

 /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

 RCC->CFGR &= (uint32_t)0xFF80FFFF;

      //位(26:24)000:MCO,  没有时钟输出
            //位(15:14)00:ADCPRE,PCLK2 2分频后作为ADC时钟频率 ADCCLK=PCLK2/2
            //位(13:11)000:PPRE2, HCLK不分频给APB2, PCLK2=HCLK
            //位(10:8)000:PPRE1,   HCLK不分频给APB1, PCLK1=HCLK
            //位(7:4)0000:HPRE,     SYSCLK不分频给AHB,HCK=SYSCLK=8Mhz
            //位(3:2)00,SWS,           HSI作为系统时钟(由硬件置1或清0)
            //位(1:0)00,SW,             HSI作为系统时钟SYSCLK=8Mhz

 

 /* Disable all interrupts and clear pending bits */

 RCC->CIR = 0x009F0000;//禁止所有时钟中断,清中断标志位
                                                  //位(23)1:CSSC,清除时钟安全系统中断
                                                  //位(20)1:PLLRDYC,清除PLL就绪中断
                                                  //位(19)1:HSERDYC,清除HSE就绪中断
                                                  //位(18)1:HSIRDYC,清除HSI就绪中断
                                                  //位(17)1:LSERDYC,清除LSE就绪中断
                                                  //位(16)1:LSIRDYC,清除LSI就绪中断
                                                  //位(12)0:PLLRDYIE,PLL就绪中断关闭
                                                  //位(11)0:HSERDYIE,HSE...
                                                  //位(10)0:HSIRDYIE,
                                                  //位( 9)0:LSERDYIE,
                                                  //位( 8)0:LSIRDYIE,
                                                  //位7-0,写0操作无意义

 

 /* Reset CFGR2 register */

 RCC->CFGR2 = 0x00000000;         

 /* 配置系统时钟频率。Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

 /* 配置Flash响应周期,并使能预取指缓存Configure the Flash Latency cycles and enable prefetch buffer */

 SetSysClock();   #ifdef VECT_TAB_SRAM  //向量表在SRAM中定义

 SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */

#else                                //向量表在FLASH中定义 

 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH.*/

#endif }

//SystemInit()函数主要流程如下
//1. RCC_CR时钟控制寄存器,第0位置1,开启内部8Mhz高速时钟HSI
//2. 设置SYSCLK=HSI=8Mhz
//    HCK=SYSCLK=8Mhz
//    PCLK1=HCLK=8Mhz
//    PCLK2=HCLK=8Mhz
//    ADCCLK=PCLK2/2=4Mhz
//    MCO,  没有时钟输出
//3. 关闭HSE外部高速时钟
//    关闭CSS时钟安全系统
//    关闭PLL锁相环
//4. 设置HSE没有被旁路,意思为HSE使用外部晶体,而不是外部时钟源
//5. 复位PLLSRC,PLLXTPRE,PLLMUL,USBPRE,为下一步重新设置新的值做准备
      复位后:
      PLLSRC=HSI/2,   PLL关闭时才可写入
      PLLXTPRE=HSE, PLL关闭时才可写入
      PLLMUL=2,          PLL关闭时才可写入,PLL开启后,PLLMUL的值才有意义,PLL=PLLSRC*PLLMUL
      USBPRE=0,         USBCLK=PLLCLK/1.5,(PLL被关闭,USBCLK同时失效,外部晶振开启成功后变为72/1.5)
//6. 禁止所有时钟中断,清中断标志位
//然后调用SetSysClockTo72()函数继续执行以下功能
//1. HSE外部高速时钟使能
//2. 使能flash预取缓冲区
//    设置SYSCLK与闪存访问时间的比例
//3. 重新设置HCLK,PCLK2,PCLK1
      HCLK = SYSCLK
      PCLK2 = HCLK
      PCLK1 = HCLK /2
//4. 又一次复位PLLSRC,PLLXTPRE,PLLMUL,
      PLLSRC=HSI/2
      PLLXTPRE=HSE不分频
      PLLMUL=2倍频输出
//5. 重设PLLSRC,PLLMUL
      PLLSRC=HSE
      PLLMUL=9倍频
//6. 使能PLL(PLLCLK=PLLSRC*PLLMUL,PLLSRC=HSE=8Mhz,PLLMUL=9)
//7. 设置SYSCLK=PLLCLK=72Mhz

其中SetSysClock函数是设置系统工作频率的,之前的代码都是用来复位时钟的 static void SetSysClock(void) { #ifdef SYSCLK_FREQ_HSE  SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz  SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz  SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz  SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz  SetSysClockTo56();  #elif defined SYSCLK_FREQ_72MHz  SetSysClockTo72(); #endif  

 /* If none of the define above is enabled, the HSI is used as System clock

    source (default after reset) */

} 最后一句的意思是:如果这些参数都没有定义,系统将使用HSI作为系统时钟。

这些参数我都没定义,到现在都搞不懂为啥用的内部8MHz时钟还是乱码

 

//这里定义了一个存储系统时钟频率的变量,利用宏定义给他赋予不同的值
#ifdef SYSCLK_FREQ_HSE
  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */
  uint32_t SystemCoreClock         = HSI_Value;        /*!< System Clock Frequency (Core Clock) */
#endif

  文件中定义了:#define SYSCLK_FREQ_HSE    HSE_VALUE 因此将使用外部时钟源作为系统时钟,HSE_VALUE即为外部时钟的频率。查看定义如下: #if !defined HSE_VALUE  #ifdef STM32F10X_CL  

 #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */

 #else

 //#define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */

#endif /* STM32F10X_CL */    

#endif /* HSE_VALUE */

将 #define HSE_VALUE    ((uint32_t)8000000)

修改为 #define HSE_VALUE    ((uint32_t)12000000)

 即设置了外部时钟为12MHz。 修改后,使用串口发送数据,电脑端接受正常。

高工
2012-04-15 21:48:03     打赏
52楼
参考资料:
stm32启动文件详解及SystemInit函数分析
http://www.ourdev.cn/thread-5466500-1-1.html

高工
2012-04-18 00:15:32     打赏
53楼
LCD的FSMC配置:
亮出来供参考,深奥的我也搞不明白,不可把玩

void LCD_FSMCConfig(void)
{
  FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  p;
/*-- FSMC Configuration ------------------------------------------------------*/
/*----------------------- SRAM Bank 4 ----------------------------------------*/
  /* FSMC_Bank1_NORSRAM4 configuration */
  p.FSMC_AddressSetupTime = 1;//地址建立时间
  p.FSMC_AddressHoldTime = 0;//地址保持时间
  p.FSMC_DataSetupTime = 2;//数据建立时间
  p.FSMC_BusTurnAroundDuration = 0;//1;//0;
  p.FSMC_CLKDivision = 0;//0;
  p.FSMC_DataLatency = 0;//0;
  p.FSMC_AccessMode = FSMC_AccessMode_A;
  /* Color LCD configuration ------------------------------------
     LCD configured as follow:
        - Data/Address MUX = Disable
        - Memory Type = SRAM
        - Data Width = 16bit
        - Write Operation = Enable
        - Extended Mode = Enable
        - Asynchronous Wait = Disable */
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;     //BANK1 的 NE4
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;     //关掉地址复用
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;                 //GRAM  当成MCU的SRAM处理
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;     //16位总线
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;  //突发模式访问,不是PSRAM所以Disable
  FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;        //写使能
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
  /* BANK 4 (of NOR/SRAM Bank) is enabled */
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
}

高工
2012-04-18 00:17:06     打赏
54楼
LCD的控制线配置:
void LCD_CtrlLinesConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* 使能 FSMC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO 时钟 */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                         RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
                         RCC_APB2Periph_AFIO, ENABLE);

  /* Set PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
     PD.10(D15), PD.14(D0), PD.15(D1) as alternate function push pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
                                GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
                                GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* Set PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
     PE.14(D11), PE.15(D12) as alternate function push pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
                                GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
                                GPIO_Pin_15;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
 
  /* Set PF.00(A0 (RS)) as alternate function push pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
 
  /* Set PG.12(NE4 (LCD/CS)) as alternate function push pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_Init(GPIOG, &GPIO_InitStructure);
}

高工
2012-04-18 00:20:16     打赏
55楼
上边两条配置好之后,就可以读取LCD的ID了:
LCD_ReadReg(0x00);  //读取LCD的ID。SSD1289的ID是0x8989

读出LCD的ID  说明你的控制线弄好了,可以进行下一步了。
ID读出来之后再进行LCD的初始化。

高工
2012-04-18 21:15:25     打赏
56楼
LCD 显示英文字符成功,有图有真相:
第一种相当难看的字体:
整体效果



局部特写


换个字体




高工
2012-04-19 18:29:29     打赏
57楼
置顶贴follow me里边有介绍

高工
2012-04-20 21:24:45     打赏
58楼
学了一下天串口接收数据,以前因为串口芯片的问题一直没有实现。现在串口片子好了,弄了下还还挺难的。

晚上实现串口控制流水灯。
因为弄了比较长的时间,通过这个实验我稍微掌握那么一点串口接收数据的出力方式了。
但有些东西比如接收到数据之后,要不要清除中断标志还不太明白
查看DataSheet后发现这样一段话:
在单缓冲器模式里,由软件读USART_DR寄存器完成对RXNE位清除。RXNE标志也可以通
过对它写0来清除。RXNE位必须在下一字符接收结束前被清零,以避免溢出错误。

即:只要从接收寄存器中读出数据,即自动清出RXNE标志位。读出数据后不需要手动清零的

我用的是是串口中断接收。首先要写串口终端函数:
在startup_stm32f10x_hd_vl.s中可以看见,串口1的中断函数是USART1_IRQHandler().
于是在文件 tm32f10x_it.c中添加了这个函数的原型:
void USART1_IRQHandler()
{
    uint8_t Res;
   
    if(USART_GetITStatus(USART1,USART_IT_RXNE)!= RESET)    //检查串口1是否接收到数据
    {
        USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
        Res = USART_ReceiveData(USART1);
        switch(Res)
        {
            case '1':
                STM_EVAL_LEDToggle(LED1);
                break;
            case '2':
                STM_EVAL_LEDToggle(LED2);
                break;
            case '3':
                STM_EVAL_LEDToggle(LED3);
                break;
            case '4':
                STM_EVAL_LEDToggle(LED4);
                break;
            default:
                STM_EVAL_LEDToggle(LED1);
                STM_EVAL_LEDToggle(LED2);
                STM_EVAL_LEDToggle(LED3);
                STM_EVAL_LEDToggle(LED4);
                break;       
        }
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    }
}
这里我实现的功能,控制LED灯反转。发送1、2、3、4分别控制相应的LED。
刚开始使用串口助手,发现每次发数据串口等就全部反转了。
后来检查发现,串口助手里边有个选项叫:发送新行。串口每次发完数据之后,要加入回车换行两个字符。把这个取消掉之后,发送数据能正确控制LED。
串口终端配置代码如下,没什么难度的不解释:
void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Configure the NVIC Preemption Priority Bits */ 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);    //设置优先级分组:先占优先级0位,从优先级4位
   
    //设置向量表的位置和偏移
    #ifdef  VECT_TAB_RAM 
        /* Set the Vector Table base location at 0x20000000 */
        NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);         //向量表位于RAM
    #else  /* VECT_TAB_FLASH  */
        /* Set the Vector Table base location at 0x08000000 */
        NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   //向量表位于FLASH
    #endif

    /* Enable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;        //USART1中断
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;        //
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器USART1
}

最后在在主函数中调用USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); 初始化串口1的接收中断,每当接收到数据之后,即可进入中断函数。

高工
2012-04-22 21:30:48     打赏
59楼
DS18B20调试中
弄了一晚上没弄出来

高工
2012-04-23 00:02:39     打赏
60楼
刚才摸了下18B20的片子,烫手了。。。。。
睡觉明天再弄了

共119条 6/12 |‹ 4 5 6 7 8 9 ›| 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]