这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » (STM32_RAM调试)库函数操作篇(库函数操作:实验2 按键输入)蒋粤 AR

共78条 6/8 |‹ 3 4 5 6 7 8 跳转至
助工
2012-05-22 21:42:35     打赏
51楼

参考网友——正点原子之寄存器操作STM32F103ZE
寄存器操作:实验1 LED流水灯
 STM32 IO简介  作为所有开发板的经典入门实验,莫过于跑马灯了。 该实验的关键在于如何控制STM32的IO口输出。了解了STM32的IO口如何输出的,就可以实现跑马灯了。通过这一节的学习,你将初步掌握STM32基本IO口的使用,而这是迈向STM32的第一步。 STM32的IO口可以由软件配置成8种模式: 1、输入浮空 2、输入上拉 3、输入下拉 4、模拟输入 5、开漏输出 6、推挽输出 7、推挽式复用功能 8、开漏复用功能 每个IO口可以自由编程,单IO口寄存器必须要按32位字被访问。STM32的很多IO口都是5V兼容的,这些IO口在与5V电平的外设连接的时候很有优势,具体哪些IO口是5V兼容的,可以从该芯片的数据手册管脚描述章节查到(I/O Level标FT的就是5V电平兼容的)。 STM32的每个IO端口都有7个寄存器来控制。他们分别是:配置模式的2个32位的端口配置寄存器CRL和CRH;2个32位的数据寄存器IDR和ODR;1个32位的置位/复位寄存器BSRR;一个16位的复位寄存器BRR;1个32位的锁存寄存器LCKR;这里我们仅介绍常用 的几个寄存器,我们常用的IO端口寄存器只有4个:CRL、CRH、IDR、ODR。 CRL和CRH控制着每个IO口的模式及输出速率。
 该寄存器的复位值为0X4444 4444,从上图可以看到,复位值其实就是配置端口为浮空输入模式。从上图还可以得出:STM32的CRL控制着每个IO端口(A~G)的低8位的模式。每个IO端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。这里我们可以记住几个常用的配置,比如0X4表示模拟输入模式(ADC用)、0X3表示推挽输出模式(做输出口用,50M速率)、0X8表示上/下拉输入模式(做输入口用)、0XB表示复用输出(使用IO口的第二功能,50M速率)。 CRH的作用和CRL完全一样,只是CRL控制的是低8位输出口,而CRH控制的是高8位输出口。这里我们对CRH就不做详细介绍了。
  给个实例,比如我们要设置PE2,3,4,5位为推挽输出。
代码如下: GPIOE->CRL&=0XFF0000FF;
  GPIOE->CRL|=0X00333300;//PE2,3,4,5推挽输出
  GPIOE->ODR|=0X003C;    //PE2,3,4,5输出高 通过这3句话的配置,我们就设置了PE2,3,4,5推挽输出。 ODR是一个端口输出数据寄存器,只用了低16位。
led.c文件部分内容:
//初始化PE2,3,4,5推挽输出.并使能PORTE时钟     
//LED IO初始化
void LED_Init(void)
{
 RCC->APB2ENR|=1<<6;    //使能PORTE时钟       
     
            
 GPIOE->CRL&=0XFF0000FF;
 GPIOE->CRL|=0X00333300;//PE2,3,4,5推挽输出
 GPIOE->ODR|=0X003C;      //PE2,3,4,5输出高
}
led.h文件部分内容:
//LED端口定义
#define LED0 PEout(2)// PE2
#define LED1 PEout(3)// PE3 
#define LED2 PEout(4)// PE4
#define LED3 PEout(5)// PE5

void LED_Init(void);//初始化

主函数:
int main(void)
{     
 Stm32_Clock_Init(9); //系统时钟设置
 delay_init(72);      //延时初始化
 LED_Init();      //初始化与LED连接的硬件接口
 while(1)
 {
  LED0=0;
  LED1=1;
  delay_ms(300);
  LED0=1;
  LED1=0;
  delay_ms(300);
 } 
}
详情请登录网友——正点原子官方论坛http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》 
源代码:实验1 LED流水灯.rar


助工
2012-05-22 22:30:27     打赏
52楼

key.c文件:
//PA0.PC13.PF11 设置成输入
void KEY_Init(void)
{
 RCC->APB2ENR|=1<<2;     //使能PORTA时钟
 RCC->APB2ENR|=1<<4;     //使能PORTC时钟
 RCC->APB2ENR|=1<<7;     //使能PORTF时钟
 GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入  
 GPIOA->CRL|=0X00000008;
   
 GPIOC->CRH&=0XFF0FFFFF;//PC13设置成输入  
 GPIOC->CRH|=0X00800000;
 
 GPIOF->CRH&=0XFFFF0FFF;//PF11设置成输入  
 GPIOF->CRH|=0X00008000;
        
 GPIOC->ODR|=1<<13;    //PC13上拉,PA0默认下拉
 GPIOF->ODR|=1<<11;    //PF11上拉
}
//按键处理函数
//返回按键值
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2!!
u8 KEY_Scan(void)

 static u8 key_up=1;//按键按松开标志 
 if(key_up&&(KEY0==0||KEY1==0||KEY2==1))
 {
  delay_ms(10);//去抖动
  key_up=0;
  if(KEY0==0)
  {
   return 1;
  }
  else if(KEY1==0)
  {
   return 2;
  }
  else if(KEY2==1)
  {
   return 3;
  }
 }else if(KEY0==1&&KEY1==1&&KEY2==0)key_up=1;     
 return 0;// 无按键按下
}
这段代码包含2 个函数,void KEY_Init(void)和u8 KEY_Scan(void),KEY_Init 是用来初始
化按键输入的IO 口的。实现PA0、PC13、PF11 的输入设置,这里和上一节的输出配置差不多,只是这里用来设置成的是输入而上一节是输出。
KEY_Scan 函数,则是用来扫描这3 个IO 口是否有按键按下。这个KEY_Scan 函数,扫描
某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的
好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。同时还有一点
要注意的就是,该函数的按键扫描是有优先级的,最优先的是KEY0,第二优先的是KEY1,
最后是KEY2(KEY2 对应WK_UP 按键)。该函数有返回值,如果有按键按下,则返回非0 值,如果没有或者按键不正确,则返回0。具体怎么实现请参考KEY_Scan 的代码。
key.h文件:
#define KEY0 PFin(11) //PF11 User_Button
#define KEY1 PCin(13) //PC13 Anti_Tamper
#define KEY2 PAin(0)   //PA0  WK_UP
 
void KEY_Init(void);//IO初始化
u8 KEY_Scan(void);  //按键扫描函数
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验2 按键输入.rar


助工
2012-05-24 16:30:00     打赏
53楼

主函数:
int main(void)
{   
 u8 t;
 u8 len; 
 u16 times=0; 
 Stm32_Clock_Init(9); //系统时钟设置
 delay_init(72);      //延时初始化
 uart_init(72,9600);  //串口初始化为9600
 LED_Init();      //初始化与LED连接的硬件接口   
 while(1)
 {
  if(USART_RX_STA&0x80)
  {       
   len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
   printf("\n您发送的消息为:\n");
   for(t=0;t<len;t++)
   {
    USART1->DR=USART_RX_BUF[t];
    while((USART1->SR&0X40)==0);//等待发送结束
   }
   printf("\n\n");//插入换行
   USART_RX_STA=0;
  }else
  {
   times++;
   if(times%5000==0)
   {
    printf("\nEEPW_ARM_DIY开发板 串口实验\n");
   }
   if(times%200==0)printf("请输入数据,以回车键结束\n"); 
   if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
   delay_ms(10);  
  }
 } 
}
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验3 串口实验.rar


助工
2012-05-25 09:35:29     打赏
54楼

寄存器操作:实验4 外部中断实验
exit.c文件:
//外部中断0服务程序
void EXTI0_IRQHandler(void)
{
 delay_ms(10);//消抖
 if(KEY2==1)  //按键2
 {
  LED0=!LED0;
  LED1=!LED1; 
 }  
 EXTI->PR=1<<0;  //清除LINE0上的中断标志位 
}

//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)
{   
 delay_ms(10);    //消抖   
 if(KEY0==0)      //按键0
 {
  LED0=!LED0;
 }else if(KEY1==0)//按键1
 {
  LED1=!LED1;
 }
 EXTI->PR=1<<11;     //清除LINE11上的中断标志位
 EXTI->PR=1<<13;     //清除LINE13上的中断标志位 
}
//外部中断初始化程序
//初始化PA0,PC13,PF11为中断输入.
void EXTIX_Init(void)
{
 RCC->APB2ENR|=1<<2;     //使能PORTA时钟 
 RCC->APB2ENR|=1<<4;     //使能PORTC时钟
 RCC->APB2ENR|=1<<7;     //使能PORTF时钟

 GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入  
 GPIOA->CRL|=0X00000008;  
 GPIOC->CRH&=0XFF0FFFFF;//PC13设置成输入  
 GPIOC->CRH|=0X00800000;
 GPIOF->CRH&=0XFFFF0FFF;//PF11设置成输入  
 GPIOF->CRH|=0X00008000;
        
 GPIOC->ODR|=1<<13;    //PC13上拉,PA0默认下拉
 GPIOF->ODR|=1<<15;    //PF11上拉

 Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
 Ex_NVIC_Config(GPIO_C,13,FTIR);//下降沿触发
 Ex_NVIC_Config(GPIO_F,11,FTIR);//下降沿触发

 MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);    //抢占2,子优先级2,组2
 MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2   
}

exit.h文件:
void EXTIX_Init(void);//IO初始化
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验4 外部中断实验.rar


助工
2012-06-01 17:15:47     打赏
55楼
实验5 独立看门狗实验
//初始化独立看门狗
//prer:分频数:0~7(只有低3位有效!)
//分频因子=4*2^prer.但最大值只能是256!
//rlr:重装载寄存器值:低11位有效.
//时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
 IWDG->KR=0X5555;//使能对IWDG->PR和IWDG->RLR的写              
   IWDG->PR=prer;  //设置分频系数  
   IWDG->RLR=rlr;  //从加载寄存器 IWDG->RLR 
 IWDG->KR=0XAAAA;//reload             
   IWDG->KR=0XCCCC;//使能看门狗 
}
//喂独立看门狗
void IWDG_Feed(void)
{
 IWDG->KR=0XAAAA;//reload             
}


int main(void)
{   
  Stm32_Clock_Init(9); //系统时钟设置
 delay_init(72);      //延时初始化
 uart_init(72,9600);  //串口初始化
 LED_Init();      //初始化与LED连接的硬件接口
 KEY_Init();          //按键初始化 
 delay_ms(300);     //让人看得到灭
 IWDG_Init(4,625);    //与分频数为64,重载值为625,溢出时间为1s   
 LED0=0;     //点亮LED0
 while(1)
 {
  if(KEY_Scan()==3)IWDG_Feed();//如果WK_UP按下,则喂狗
  delay_ms(10);
 }; 
}
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验5 独立看门狗实验.rar

助工
2012-06-01 20:56:10     打赏
56楼
实验6 窗口看门狗实验
//保存WWDG计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
//初始化窗口看门狗
//tr   :T[6:0],用于存储计数器的值
//wr   :W[6:0],用于存储窗口值
//fprer:窗口看门狗的实际设置
//低2位有效.Fwwdg=PCLK1/4096/2^fprer.
void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{        
 RCC->APB1ENR|=1<<11; //使能wwdg时钟
 WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.           
 WWDG->CFR|=fprer<<7;    //PCLK1/4096再除2^fprer
 WWDG->CFR|=1<<9;        //使能提前唤醒中断
 WWDG->CFR&=0XFF80;    
 WWDG->CFR|=wr;      //设定窗口值    
 WWDG->CR|=WWDG_CNT|(1<<7); //开启看门狗,设置7位计数器            
 MY_NVIC_Init(2,3,WWDG_IRQChannel,2);//抢占2,子优先级3,组2   
}
//重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
{
 WWDG->CR|=(cnt&0x7F);//重设置7位计数器
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{         
 u8 wr,tr; 
  wr=WWDG->CFR&0X7F;
 tr=WWDG->CR&0X7F;
 if(tr<wr)WWDG_Set_Counter(WWDG_CNT);//只有当计数器的值,小于窗口寄存器的值才能写CR!!         
 WWDG->SR=0X00;//清除提前唤醒中断标志位
 LED1=!LED1;
}
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验6 窗口看门狗实验.rar

助工
2012-06-02 20:02:38     打赏
57楼
//定时器3中断服务程序 
void TIM3_IRQHandler(void)
{                 
 if(TIM3->SR&0X0001)//溢出中断
 {
  LED1=!LED1;                             
 }      
 TIM3->SR&=~(1<<0);//清除中断标志位     
}
//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void Timerx_Init(u16 arr,u16 psc)
{
 RCC->APB1ENR|=1<<1;//TIM3时钟使能   
  TIM3->ARR=arr;  //设定计数器自动重装值//刚好1ms   
 TIM3->PSC=psc;  //预分频器7200,得到10Khz的计数时钟
 //这两个东东要同时设置才可以使用中断
 TIM3->DIER|=1<<0;   //允许更新中断    
 TIM3->DIER|=1<<6;   //允许触发中断   
 TIM3->CR1|=0x01;    //使能定时器3
   MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占1,子优先级3,组2         
}
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:实验7 定时器中断实验.rar

助工
2012-06-02 20:05:19     打赏
58楼

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void PWM_Init(u16 arr,u16 psc)
{        
 //此部分需手动修改IO口设置
 RCC->APB1ENR|=1<<1;       //TIM3时钟使能   

 GPIOE->CRL&=0XFFFFF0FF;//PE2输出
 GPIOE->CRL|=0X00000400;//浮空输入
    
 GPIOA->CRL&=0X0FFFFFFF;//PA7输出
 GPIOA->CRL|=0XB0000000;//复用功能输出   
 GPIOA->ODR|=1<<7;//PA7上拉 

 TIM3->ARR=arr;//设定计数器自动重装值
 TIM3->PSC=psc;//预分频器不分频
 
 TIM3->CCMR1|=7<<12;  //CH2 PWM2模式  
 TIM3->CCMR1|=1<<11; //CH2预装载使能   

 TIM3->CCER|=1<<4;   //OC2 输出使能   

}
详情请登录网友——正点原子官方论坛
http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:
实验8 PWM输出实验.rar


助工
2012-06-02 20:11:27     打赏
59楼
主要修改了这些地方,详情见代码:
 RCC->AHBENR|=1<<8;       //使能FSMC时钟  
  RCC->APB2ENR|=1<<3;      //使能PORTB时钟
 RCC->APB2ENR|=1<<5;      //使能PORTD时钟
 RCC->APB2ENR|=1<<6;      //使能PORTE时钟
 RCC->APB2ENR|=1<<7;      //使能PORTF时钟
  RCC->APB2ENR|=1<<8;      //使能PORTG时钟
 RCC->APB2ENR|=1<<0;      //使能AFIO时钟 
 GPIOB->CRL&=0XFFFFFFF0;//PB0 推挽输出 背光
 GPIOB->CRL|=0X00000003;   
 //PORTD复用推挽输出  
 GPIOD->CRH&=0X00FFF000;
 GPIOD->CRH|=0XBB000BBB;
 GPIOD->CRL&=0XFF00FF00;
 GPIOD->CRL|=0X00BB00BB;    
 //PORTE复用推挽输出  
 GPIOE->CRH&=0X00000000;
 GPIOE->CRH|=0XBBBBBBBB;
 GPIOE->CRL&=0X0FFFFFFF;
 GPIOE->CRL|=0XB0000000;                      
 //PORTG12复用推挽输出                   
 GPIOG->CRH&=0XFFF0FFFF;
 GPIOG->CRH|=0X000B0000;
 //A0
 GPIOF->CRL&=0XFFFFFFF0;//PF0->RS
 GPIOF->CRL|=0X0000000B;
     
 //寄存器清零
 //bank1有NE1~4,每一个有一个BCR+TCR,所以总共八个寄存器。
 //这里我们使用NE4 ,也就对应BTCR[6],[7]。       
 FSMC_Bank1->BTCR[6]=0X00000000;
 FSMC_Bank1->BTCR[7]=0X00000000;
 FSMC_Bank1E->BWTR[6]=0X00000000;
 //操作BCR寄存器 使用异步模式
 FSMC_Bank1->BTCR[6]|=1<<12;//存储器写使能
 FSMC_Bank1->BTCR[6]|=1<<4; //存储器数据宽度为16bit     
 //操作BTR寄存器           
 //3个HCLK(HCLK=72M)因为液晶驱动IC的写信号脉宽,最少也得50ns。72M/3=24M=42ns,已经超频了。  
 FSMC_Bank1->BTCR[7]|=1<<9; //数据保存时间为3个HCLK   
 //闪存写时序寄存器 
 FSMC_Bank1E->BWTR[6]=0x0FFFFFFF;//默认值
 //使能BANK4(PC卡设备)
 FSMC_Bank1->BTCR[6]|=1<<0;    
   
 delay_ms(50); // delay 50 ms
 LCD_WriteReg(0x0000,0x0001);
 delay_ms(50); // delay 50 ms
  //因为液晶驱动IC的读数据的时候,速度不能太快,尤其对1289这个IC。
 FSMC_Bank1->BTCR[7]|=0XF<<8; //数据保存时间为16个HCLK   
 DeviceCode = LCD_ReadReg(0x0000);  
 FSMC_Bank1->BTCR[7]&=~(0XF<<8); //数据保存时间为0
 //因为液晶驱动IC的写信号脉宽,最少也得50ns。72M/3=24M=42ns,已经超频了。  
 FSMC_Bank1->BTCR[7]|=1<<9;      //数据保存时间为3个HCLK 
详情请登录网友——正点原子官方论坛http://www.openedv.com/forums/list.htm或下载《STM32不完全手册V2.0》
源代码:
实验9 TFT液晶FSMC驱动显示实验.rar

高工
2012-06-02 21:12:56     打赏
60楼
寄存器操作fsmc,不错不错!

共78条 6/8 |‹ 3 4 5 6 7 8 跳转至

回复

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