OpenEdv-开源电子网

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

点亮LED:CMSIS库到原子示例库的转换

[复制链接]

9

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2013-7-29
在线时间
0 小时
发表于 2013-7-30 18:20:00 | 显示全部楼层 |阅读模式
工作板上的LED初始化程序代码如下:
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);

原子的示例跑马灯原来为:
void LED_Init(void)
{
RCC->APB2ENR|=1<<3;    //使能PORTB时钟    
   
GPIOB->CRL&=0XFF0FFFFF; 
GPIOB->CRL|=0X00300000;//PB.5 推挽输出    
        GPIOB->ODR|=1<<5;      //PB.5 输出高   
}

我修改时,不知道下面的推挽输出,输出高这几项和上面的库设置该怎样对应,我改的如下:
void LED_Init(void)
{
{//JQB ADD
    RCC->APB2ENR|=1<<2;    //使能PORTA时钟   
}
   
GPIOA->CRL&=?;//0XFF0FFFFF; 
GPIOB->CRL|=?;//0X00300000;//PB.5 推挽输出    
        GPIOB->ODR|=?;//1<<5;      //PB.5 输出高
}

查了CMSIS库的定义如下:
typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
无法和原子的示例代码中的输出类型对应上.

求高手指点!!
先谢谢了.









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

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2010-12-21
在线时间
1 小时
发表于 2013-7-30 18:24:23 | 显示全部楼层
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

RCC->APB2ENR|=1<<3;    //使能PORTB时钟
是相对应的。


GPIO_SetBits(GPIOB,GPIO_Pin_5);

GPIOB->ODR|=1<<5;      //PB.5 输出高
是相对应的。
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2010-12-21
在线时间
1 小时
发表于 2013-7-30 18:27:33 | 显示全部楼层
GPIOB->CRL&=0XFF0FFFFF; 
GPIOB->CRL|=0X00300000;//PB.5 推挽输出   
第一行代码令PB5那一位清0,变成模拟输入GPIO_Mode_AIN功能
第二行代码令PB5那两位变成3,变成推挽输出GPIO_Mode_Out_PP功能
使用第二行的前必须先执行第一行。


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_Init(GPIOB, &GPIO_InitStructure);
相对应
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2010-12-21
在线时间
1 小时
发表于 2013-7-30 18:29:53 | 显示全部楼层
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5=1 输出高电平
  GPIO_ResetBits(GPIOB,GPIO_Pin_5); //PB.5=0 输出低电平
回复 支持 反对

使用道具 举报

9

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2013-7-29
在线时间
0 小时
 楼主| 发表于 2013-7-31 08:56:51 | 显示全部楼层
回复【3楼】liangwz:
---------------------------------
一.置位问题:
如果使用PB0那一位,是不是就要: 
GPIOB->CRL&=0XFFFFFFF0;   
GPIOB->CRL|=0X00000003;//PB.0 推挽输出    
如果使用PB1那一位,是不是就要:
GPIOB->CRL&=0XFFFFFF0F;  
GPIOB->CRL|=0X00000030;//PB.1 推挽输出   
以此类推?

我按如上改了个,烧写到工作板上,LED灯亮不了.
1)是不是和时间频率有关系?我工作板上用的HSE_VALUE如下图:

2)与启动文件startup_stm32f10x_hd.s有没有关系?另外我看了一下我的工作工程中有4个启动文件,那么启动文件是如何确定的?如下图:





二.GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;这一句在上面的函数中没有体现呀?!
与原子提供的下面这个函数有没有关系呢?
//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16  
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;   
MYRCC_DeInit();  //复位并配置向量表
  RCC->CR|=0x00010000;  //外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等待外部时钟就绪
RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2个单位
RCC->CFGR|=PLL<<18;   //设置PLL值 2~16
RCC->CFGR|=1<<16;  //PLLSRC ON 
FLASH->ACR|=0x32;  //FLASH 2个延时周期

RCC->CR|=0x01000000;  //PLLON
while(!(RCC->CR>>25));//等待PLL锁定
RCC->CFGR|=0x00000002;//PLL作为系统时钟  
while(temp!=0x02)     //等待PLL作为系统时钟设置成功
{   
temp=RCC->CFGR>>2;
temp&=0x03;
}    
}

三.我现在的这些疑问,通过哪些哪些途径自己可以解决?比如总的学习步骤?要看哪几本书?原子的视频资料中有相关的深入介绍吗?


又抛出好几个问题,这些问题也作为我这个菜鸟的成长记录,还请前辈们多多指教,先谢谢了.


回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-7-31 11:14:02 | 显示全部楼层
回复【5楼】jqb:
---------------------------------
1,是的,检查你的PB时钟开启了么?
1)和你这个时钟设置无关,这里一般设置为8Mhz也就是你外部HSE晶振的频率.
2)看此贴:http://www.openedv.com/posts/list/313.htm
2,你设置IO对应的CRL/CRH的4个位的时候,就已经设置速度了,具体你可以去看看CRL.CRH寄存器的详细描述.
 Stm32_Clock_Init,这函数是系统时钟初始化,以及系统外设复位.主要是把8M晶振频率倍频上去给系统做时钟.
3,论坛多搜索,寄存器的问题就直接看<stm32参考手册>找寄存器描述,看描述,一般都比较好理解.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

9

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
80
金钱
80
注册时间
2013-7-29
在线时间
0 小时
 楼主| 发表于 2013-7-31 12:55:33 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
谢谢原子的帮助和耐心解答!

工作板的LED灯仍然不亮.
我现在修改的原子的跑马灯的代码如下:

0.使用startup_stm32f10x_hd.s
比较工作板使用的这个文件,将跑马灯工程的这个文件做了修改:
;Stack_Size      EQU     0x00000800
Stack_Size      EQU     0x00000400

;Heap_Size       EQU     0x00000000
Heap_Size       EQU     0x00000200


1.增加宏, 在led.h:
#define LED_C0 PCout(0)
#define LED_C1 PCout(1)
#define LED_A0 PAout(0)
#define LED_A1 PAout(1)

2.修改main:
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司
int main(void)
{  
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72);   //延时初始化
LED_Init();   //初始化与LED连接的硬件接口
while(1)
{
// LED0=0;
// LED1=1;
{//JQB ADD
LED_C0=1;
LED_C1=1;
LED_A0=1;
LED_A1=1;
}
delay_ms(300);
// LED0=1;
// LED1=0;
{//JQB ADD
LED_C0=0;
LED_C1=0;
LED_A0=0;
LED_A1=0;
}
delay_ms(300);
}  
}

3.修改led的初始化函数,led.c中:
//初始化PB5和PE5为输出口.并使能这两个口的时钟    
//LED IO初始化
void LED_Init(void)
{
{//JQB ADD
RCC->APB2ENR|=1<<2;    //使能PORTA时钟
RCC->APB2ENR|=1<<4;    //使能PORTC时钟    
GPIOA->CRL&=0XFFFFFFF0;
GPIOA->CRL|=0X00000003;//PA.0推挽输出
GPIOA->ODR|=1<<0;      //PA.0输出高 

GPIOA->CRL&=0XFFFFFF0F;
GPIOA->CRL|=0X00000030;//PA.1推挽输出
GPIOA->ODR|=1<<1;      //PA.1输出高 

GPIOC->CRL&=0XFFFFFFF0;
GPIOC->CRL|=0X00000003;//PC.0推挽输出
GPIOC->ODR|=1<<0;      //PC.0输出高 

GPIOC->CRL&=0XFFFFFF0F;
GPIOC->CRL|=0X00000030;//PC.1推挽输出
GPIOC->ODR|=1<<1;      //PC.1输出高
}
/* 
RCC->APB2ENR|=1<<3;    //使能PORTB时钟    
RCC->APB2ENR|=1<<6;    //使能PORTE时钟
   
GPIOB->CRL&=0XFF0FFFFF; 
GPIOB->CRL|=0X00300000;//PB.5 推挽输出    
    GPIOB->ODR|=1<<5;      //PB.5 输出高
 
GPIOE->CRL&=0XFF0FFFFF;
GPIOE->CRL|=0X00300000;//PE.5推挽输出
GPIOE->ODR|=1<<5;      //PE.5输出高 
*/
}


解决方法:
1.工作板是通过SD卡烧.img文件来升级的,那么应该是有操作系统的了?是不是需要将delay.c文件中使用到的宏OS_CRITICAL_METHOD先定义呢?

2.位带地址是不是不对:
工作板的GPIOA 的基址与原子跑马灯的示例中的基址不同:
//工作板:
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)

//原子示例:
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
//#define GPIOA_ODR_Addr    (GPIOA_BASE) //0x40010800  //JQB ADD
仔细分析,原子的是对的,因为上面的那个GPIO_TypeDef结构中的ODR是要偏移12个字节的.

3.由于工作板是用库version V3.1.2开发的,我就在原子提供的跑马灯的库示例程序上改;
  结果,灯还是不亮!

4.修改了工程的属性,灯终于亮了.
  那么是哪个工程属性影响了呢?继续:

5.原因找到了,如下图所示:



上图中的IROM1的Start与Size正是原因所在.工程默认的这2个参数分别为:0x8000000和0x20000;
哎,工作板上的这2个参数原来这么重要呀.
这2个参数是做什么用的呢?继续:





回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-16 04:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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