用户注册 | 登录 | 帮助中心 | 网站地图 | 加入收藏 | English

网站首页 产品列表 软件下载 技术资料 付款方式 发货查询 关于我们 淘宝商城 论坛
搜索 高级/组合搜索
网站文章
所有文章
站内新闻
单片机工具资料
汇编程序实例
C语言程序实例
单片机提高资料
单片机初学资料
单片机软件下载
单片机技术资料
  您的位置: 首页 >> 文章列表 >> stm32调试记
stm32调试记

作者:单片机爱好者  转载自:单片机工具之家  发布日期:2011-4-18

第一节: 陌生的她和大叔 
       人近中年,不知不觉竟然成为孩子的父亲,不知不觉竟然成为别人的大叔,心中很是彷徨,我已不再年少。前些日子学习stm8,一口气工作近2个星期,当时精神饱满,心中很是得意,原来我也可以年轻。谁知放假去了次青岛和家人度假回来后竟然感冒了一个星期,哎,我还是老了。 
       写完stm8调试记后,就想践踏一下stm32,就像大叔和美女。。。因为只有美女才能让大叔觉得年轻,只有美女才能让大叔精力旺盛,stm32是我的美女吗?我不知道,我要接近她,我要驾驭她。 
     KEIL 的大名人尽皆知,51年代就大放异彩。说到这儿,不得不说一下那些为电子公益事业做出贡献的先行者们。甚是怀念那个年代,丁丁,老万,所长,午夜听风,龙啸九天等诸多大虾。他们推广keil,他们无私的奉献,就像现在的老key一样,知无不言,言无不尽。 
     我使用的环境: keil mdk 350            
 St 的 三合一板 
板子虽小,还是可以做很多事情的,白菜老弟做的板子据说很强势,已经预定,现在先解下渴,玩玩只有一个STM32F103C8T6的小家碧玉。 
Mdk350集成了st的st link,所以只要在OPTION FOR TARGET 的 DEBUG 和UTILITIES下选择st link debug就可以正确连接。库使用的是v2.01 
我要让她跑起来,我需要做什么? 
我要有一个时钟,目标是48mhz,这是为了以后调试usb 
STM32的时钟和STM8的时钟基本上是一样的。她内部有个8mhz的振荡器,不过我不打算用它。三合一板外部焊接了一个8mhz的晶振我要用她做时钟源。 
时钟初始化:  
             RCC_DeInit();  //恢复默认值这没什么用,不写他也不影响运行 
          RCC_HSEConfig(RCC_HSE_ON ); //启动外部时钟 
          while(!RCC_GetFlagStatus(RCC_FLAG_HSERDY));//等待外部时钟稳定 
          FLASH_SetLatency(FLASH_Latency_1); //48mhz运行时,flash要加一个等待周期 
       其实刚开始时我没有加这个延时,也没有什么不良的反应,不知道时间长了会不会有问题 
          FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//预缓冲使能 
          RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);//pll输出是外部时钟的6倍 
          RCC_PLLCmd(ENABLE); //使能pll 
          while(!RCC_GetFlagStatus(RCC_FLAG_PLLRDY));//等待pll稳定 
          RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//切换到PLL时钟 
          while(RCC_GetSYSCLKSource()!=0x8);//等待系统时钟稳定       
             RCC_PCLK1Config(RCC_HCLK_Div2);//低速时钟为24mhz 
          RCC_PCLK2Config(RCC_HCLK_Div1);//高速时钟为48mhz 
经过上面的设置,时钟正是工作,我们可以通过这个函数RCC_GetClocksFreq(); 
来验证 
      RCC_ClocksTypeDef  RCC_Clocks_T; 
      RCC_GetClocksFreq( &RCC_Clocks_T); 
RCC_Clocks_T中反应了sys clk,  HCLK  PCLK1,PCLK2, ADC CLK的频率。 
时钟有了,我们还要干点什么?板上有她唯一的外设,led小灯。我要让处于pb5的led亮。 
     //首先开启PB口的时钟,pb口在高速apb2上 
          RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE ); 
 下面要进行pb口的初始化 
          GPIO_InitTypeDef  GPIOB_STR;   //定义一个结构变量用于初始化                
           GPIOB_STR.GPIO_Pin = GPIO_Pin_5;  //选择pb5 
            GPIOB_STR.GPIO_Speed = GPIO_Speed_10MHz; //最大10mhz输出 
            GPIOB_STR.GPIO_Mode  = GPIO_Mode_Out_PP;//推挽输出 
            GPIO_Init( GPIOB,&GPIOB_STR);  //配置pb5      
Pb5已经配置好了,下面我要点亮led,pb5要输出1 
        GPIO_SetBits( GPIOB,GPIO_Pin_5); 
相反熄灭她如下: 
        GPIO_ResetBits( GPIOB,GPIO_Pin_5); 
这一节就到这,意法的库真是好东西,stm8调试的时候没有使用是因为实在不愿看那么多的代码。现在学习stm32,顺便把她的库看了看,觉得虽然庞大琐碎,但结构很优美,便用了起来。不过我怕用习惯了,把我自己用傻了,以后换别的cpu时,不会用了。 
第二节 定时,中断,和意法的风骚      
         玩cpu吗当然等玩定时器,重要性在stm8一文中已有描述,这里不再多说。 
     我要使用tim2实现1s定时,这有些长不够实用,但是我只是玩玩。      
     第一步要配置时钟 
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_SPI2,ENABLE); 
      Tim2处于时钟树的apb1上。 
      下面是初始化代码 
                TIM2->PSC |=24000; //设置预分频,实现1ms 
           TIM2->ARR = 1000;  //1s产生一次中断 
           TIM2->DIER |=0X1;  //允许tim2更新中断 
           NVIC->ISER[0] |= (u32)(1<<TIM2_IRQChannel); //开tim2中断 
           TIM2->CR1 |=0X1;//启动tim2 
      说到这,不能不说意法的风骚,刚开始时翻遍手册也没看到nvic部分的说明,所以第一版本的tim2初始化没有nvic部分,以至不能进tim2的更新中断,后查阅阿莫的论坛才知有c_m3权威指南一物,实在让人无语。这是意法的风骚,这是新手的灾难。 
         每次新建工程时,keil会自动生成一个文件stm32f10x.s,在里面有中断向量表的描述。将相应的中断函数名实例化,就能实现中断入口。 
      我的tim2中断函数 
void TIM2_IRQHandler(void)//这个函数名能在stm32f10x.s中找到 

           static u8 flag; 
           if( flag ) 
           {             
               GPIO_SetBits( GPIOB,GPIO_Pin_5); //下面能实现上文说的led以0.5hz闪烁 
                     flag = FALSE; 
           } 
           else 
           {             
               GPIO_ResetBits( GPIOB,GPIO_Pin_5);  
                   flag = TRUE;             
           }       
           TIM2->SR &=0XFFFE;  //清楚更新标志

上面没有用库函数,是因为我想自己的头脑里脉络更清楚,更复合我自己的风格。其实用库会简单 
第三节 SPI和懒懒的我 
       调试stm8时没有调spi实在是因为没有接口,在加上我这人懒散最终没有调它,如果是美女,我就不会这么客气了吧。 
       最近身体欠佳,总感觉力不从心。又觉得时间匆匆,再不加把力气真要荒废此生,便生出无奈。 
      闲话少说,说说spi吧。三合一板只有一个cpu,但它却有两个spi,我用飞线将他们互联,便形成了一个完整的spi通讯接口。 
Spi2处于时钟树的apb1,spi1处于时钟树的apb2,时钟部分已将apb1配置为24mhz 
Apb2为48mhz 
首先开启spi2和spi1时钟 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2\ 
                  |RCC_APB1Periph_SPI2,         \\这个是spi2的选项 
                  ENABLE); 
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB\ 
                                   |RCC_APB2Periph_SPI1\ //这个是spi1的选项 
                                  |RCC_APB2Periph_GPIOA\                                
                                                          |RCC_APB2Periph_USART1,ENABLE                                  
                                                         ); 
下面是spi的初始化 
       u32 x;        
           u8 y;       
           SPI_InitTypeDef SPI_X; 
           SPI_X.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全双工 
           SPI_X.SPI_Mode = SPI_Mode_Slave;//式 
           SPI_X.SPI_DataSize = SPI_DataSize_8b;// 
           SPI_X.SPI_CPOL = SPI_CPOL_High;//时钟空闲是为高 
           SPI_X.SPI_CPHA = SPI_CPHA_2Edge;// 
           SPI_X.SPI_NSS  = SPI_NSS_Soft;//软件控制 
           SPI_X.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; 
             SPI_X.SPI_FirstBit = SPI_FirstBit_MSB; 
           SPI_Init(SPI2,&SPI_X); 
               SPI2->CR2 |= (1<<SPI_FLAG_RXENIE)|(1<<SPI_FLAG_TXENIE);//接受和发送 中断 
           NVIC->ISER[1] |= 0X10;//开spi2中断 
           SPI_X.SPI_Mode = SPI_Mode_Master; 
           SPI_Init(SPI1,&SPI_X); //spi1为主 
           SPI1->CR2 |= (1<<SPI_FLAG_RXENIE)|(1<<SPI_FLAG_TXENIE); 
           NVIC->ISER[1] |= 0X8; 
           SPI_Cmd(SPI2,ENABLE); 
           SPI_Cmd(SPI1,ENABLE);//使能spi1和spi2 
           SPI2->DR = 0Xaa;//发送数据 
中断处理函数 
void SPI1_IRQHandler( void ) 

      u16 x; 
          if( SPI1->SR &0X1)             
          {              
                 x = SPI1->DR; 
           }             
          if( SPI1->SR&0x2 )  
          {               
                  SPI1->DR =++test_data1; 
          } 

void SPI2_IRQHandler( void ) 

      vu16 x; 
          if( SPI2->SR &0X1) 
          {          
                 x = SPI2->DR; 
                 if( sam_data < SIZE_BUF ) 
                 { 
                    sam_data1[ sam_data++ ] =x; 
                 } 
                 else 
                 { 
                     sam_data = 0;      
                 } 
           } 
          if( SPI2->SR&0x2 )  
          { 
              SPI2->DR =++test_data; 
/*                  if(test_data1!=0) 
                  {             
                      test_data1 --;              
                  } 
                  else 
                  {            
                      test_data1 =10; 
                  }         */ 
          } 

外设使用的时候一定要先配置好io的使用模式。我就因为没有配置而吃了大亏。刚开始时收发怎么也不正常,后设置了io的方式才能工作。这大概是对新的事物还不熟悉。 
Io的模式无非是,出的数据流设成输出,入的数据流设成输入,什么可说。 
   关于spi的代码,不是好的风格,其中库夹杂着自己的方法,如果在严格的风格上这不叫方法,叫发疯。 
第四节:串口和新凤霞 
     最近听新凤霞的花为媒,让我有绕梁三日的感觉。喜欢的朋友可以听一下。老艺术家的东西越来越少了。时代在进步,我们在放弃。但放弃的都是优良的传统,如清廉,孝道,公正。 
     我手里有两个自己做的ch341转串口线缆,将小板的pa9(u1_TX,设置成推挽输出),和pa10(U1_RX,上拉输入) 
和ch341相连,就完成了硬件配置。 
     我要实现的功能,当cpu收到计算机发来的0XAA时,发送8个0X55,在上电时cpu主动发送一次8个0X55. 
     首先配置时钟, 
           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB\ 
                                     |RCC_APB2Periph_SPI1\ //这个是spi1的选项 
                                     |RCC_APB2Periph_GPIOA\                  
                                        |RCC_APB2Periph_USART1,ENABLE         //这个是串口项                
                                                         ); 
下面是初始化: 
        USART_InitTypeDef uart_x; 
        NVIC_InitTypeDef nvic_x; 
        USART_Cmd(USART1,ENABLE); //使能串口 
        uart_x.USART_BaudRate = 19200;//19200, 8, n ,1 
        uart_x.USART_WordLength = USART_WordLength_8b; 
        uart_x.USART_StopBits = USART_StopBits_1; 
        uart_x.USART_Parity = USART_Parity_No; 
        uart_x.USART_Mode = USART_Mode_Rx |USART_Mode_Tx;//发送和接受 
        uart_x.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
        USART_Init(USART1,&uart_x); 
        USART_ITConfig(USART1,USART_IT_TC,ENABLE);//使能发送完成中断 
        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接受满中断 
        nvic_x.NVIC_IRQChannel = USART1_IRQChannel;//nvic的库开启方法 
        nvic_x.NVIC_IRQChannelCmd = ENABLE; 
        NVIC_Init(&nvic_x); 
中断函数 
void USART1_IRQHandler( void ) 

          vu16 x;           
          vu16 y ; 
          y = USART1->SR;//读状态 
         if(y & 0X20)//如果是非空中断 
         {  
                  x = USART1->DR&(u16)0xff;  
                // USART_SendData(USART1,0X55); 
                if( x == 0xaa ) 
                {                  
                   lentch_x = 0; 
                   USART1->CR1 |=(u16)0X8;//启动一次发送                  
                } 
         }   
         if(y & 0X40)//发送完成中断 
         {                 
                if(lentch_x < 8 ) 
                { 
                    USART1->DR = 0X55; 

                        lentch_x++; 
                } 
                else 
                { 
                         USART1->CR1 &=(u16)0XFFF7;; //清楚标志
                } 
         } 

这次完全使用了库,哈。过两天使用dma试试,接下来还有adc等没有测试,可板子太小了可发挥的余地不多,就剩usb了,可是它太不好肯,得好好的准备准备,过阵子白菜的板子到了在研究。

【版权声明】
  1. 任何网站转载本站内容必需注明“来源:单片机工具之家”。
  2. 本网转载自其它媒体的信息,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。
  3. 未经本站明确许可,任何网站不得非法盗链软件下载连接及抄袭本网站原创内容资源。
  4. 违反上述声明者,本网将追究其相关法律责任。谢谢!


关于我们
网站介绍
联系我们
付款方式
银行汇款
货到付款
发货方式
快递运输
上门自提
售后服务
退换货政策
质保承诺
购买方式
购物流程
在线订购

公司名称:深圳市乾龙盛电子科技有限公司    网站名称:单片机工具之家
公司地址:广东省深圳市宝安区龙华镇民治路潜龙花园惠宁阁13-G   联系电话:0755-28187975  13715306011  传真:0755-28187976
展销柜台:广东省深圳市福田区新亚洲电子商城二期三楼N3D033室(华强电子世界附件)【查看地图】   联系电话:0755-82543360
:淘宝商店   :qls@cxqmcu.com   :qls@cxqmcu.com
销售点击Q我:243355504 (唐永红)先生   技术支持点击Q我:443935535 (钟先生)
网站版权:单片机工具之家  粤ICP备09028690号