249018563 发表于 2017-7-4 22:06:31

圆梦那年3(c语言)---废话少说上干货

本帖最后由 249018563 于 2017-7-14 16:35 编辑

1、安装编程环境 keil5网盘地址:http://pan.baidu.com/s/1miRyj3a
2、坚持用到什么学什么的实用主义原则,绝不多学一点点{:5_95:}   东拼西凑能实现我要的功能就好
3、第一章 学习STM32
(以前上学只让用飞思卡尔的芯片(MC92s12)),从头学吧,还能跟大家交流一下,虽然感觉帖子发错地方了。。。

第一课:点亮LED.
文件1:test.c
----------------------------------------------------------------------------------------------------------------------
#include "sys.h"
#include "usart.h"               
#include "delay.h"       
#include "led.h"
/*****************************************************
File:LED应用
Author:                   Version:1.0   Data:2016/09/08
Description:    LED闪烁
**********************************************************/
int main(void)
{               
        Stm32_Clock_Init(9); //系统时钟设置 外部8m晶振   <----就这个地方其实是是为了得到下边delay_init(72) 72 这个参数   72= 8*9
        delay_init(72);             //延时初始化   9倍频到72m
        LED_Init();                         //初始化与LED连接的硬件接口 pc13推挽输出
        while(1)
        {
                LED = 1;//   pc13口
                delay_ms(500);   //延时500毫秒
                LED = 0;
                delay_ms(500);    //延时500毫秒
        }       
}
----------------------------------------------------------------------------------------------------------------------------
文件2:sys.c
-----------------------------------------------------------------------------------------------------------------------------
#include "sys.h"
//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个单位(因为是从2开始的,设置0就是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;
        }   
}                  
-----------------------------------------------------------------------------------------------------------------------------
文件3:delay.c
---------------------------------------------------------------------------------------------------------------------------
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS                                                 //如果需要支持OS.
        u32 reload;
#endif
        SysTick->CTRL&=~(1<<2);                                        //SYSTICK使用外部时钟源       
        fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS                                                 //如果需要支持OS.
        reload=SYSCLK/8;                                                //每秒钟的计数次数 单位为K          
        reload*=1000000/delay_ostickspersec;        //根据delay_ostickspersec设定溢出时间
                                                                                        //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右       
        fac_ms=1000/delay_ostickspersec;                //代表OS可以延时的最少单位          
        SysTick->CTRL|=1<<1;                                           //开启SYSTICK中断
        SysTick->LOAD=reload;                                         //每1/delay_ostickspersec秒中断一次       
        SysTick->CTRL|=1<<0;                                           //开启SYSTICK   
#else
        fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   
#endif
}               
void delay_ms(u16 nms)                        //毫秒延时
{                                   
        u32 temp;                  
        SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;                                 //清空计数器
        SysTick->CTRL=0x01 ;                                  //开始倒数
        do
        {
                temp=SysTick->CTRL;
        }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
        SysTick->CTRL=0x00;                                     //关闭计数器
        SysTick->VAL =0X00;                                       //清空计数器                    
}                        
----------------------------------------------------------------------------------------------
文件4:led.c
----------------------------------------------------------------------------------------------------------
#include "led.h"
/*********************************************************
Copyright (C), 2016-2026, YFRobot.
www.yfrobot.com
File:LED驱动代码
Author:pinggai    Version:1.0   Data:2016/09/08
Description: Balance-STM32 V2.0 LED驱动代码
Others: 使用端口 PC13
         使用硬件资源 PC13
**********************************************************/          
/******************************************************
Function:   void LED_Init(void)
Description:LED IO初始化,设置PC13为输出端口
******************************************************/
void LED_Init(void)
{
        RCC->APB2ENR|=1<<4;   //使能PORTC时钟(|= 可以防止操作其他位)
//APB2负责AD,I/O,串口1,高级TIM
//APB1负责DA,串口345,普通TIM,USB,IIC,CAN
        GPIOC->CRH&=0XFF0FFFFF;//高8位 8-15口 ,0为13口,13口清空 ,不影响其他口
        GPIOC->CRH|=0X00300000; //PC.13推挽输出 ,0x4模拟输入、0x3推挽输出(00 11,00指推挽输出,11指输出模式 50mhz)
                                //0x8 上拉或下拉输入,0xb复用输出
       
        GPIOC->ODR|=1<<13;      //PC.13输出高 odr端口输出数据寄存器
}
-----------------------------------------------------------------------


--------------------------------------------------------------------------------------------------------------------
好吧,其实注释已经很详细了,不过我估计这论坛大多数人不知道硬件c语言。其实都是c语言没什么区别的,我就自己督促自己学习吧。
这里给大家讲个小知识吧,我也复习一下,尽量给大家将明白,下面这两句话是让指定位变为0或1 而不改变其他位
GPIOC->CRH&=0XFF0FFFFF;   //高8位 8-15口 ,0为13口,13口清空 ,不影响其他口
GPIOC->CRH|=0X00300000; //PC.13推挽输出,其他口与0或运算 不影响其他口
不知道大家看到这两句话没
我来简化一下
-------------------------------------------------------------------------------------------------------------------------------------------
知识点 &:与运算    0&0 ==0, 0&1==0 , 1&1=1

第一句简化为:a&=0//即a= a&0,这句话让a总为false

我们来分析一下1、假如 a==0现在让a和0做相与运算即 a=0&0a结果为0   即false
                        2、假如 a!=0(假如a为1不等于0)现在让a和0做相与运算即a=1&0 a结果也为0 即false

总结:a&=0 不论a以前为什么数,经过这句话运算后a被赋值为0
         
------------------------------------------------------------------------------------------------------------------
知识点:| 或运算   0|0==0    ,0|1==1,1|1==1
第二句:a|=1   //经运算后a总为true大家自己分析吧



---------------------------------------------------------------------------
对了还有个好玩的事,不知道大家看到没,死循环,这在硬件编程中很常见(之前那都是硬件寄存器配置,管用的只有下边这句话{:5_98:} ,换句话说那些都是前戏,让LED闪的其实就这点)
下边这段程序就是让LED 亮500毫秒,然后灭500毫秒,眼睛看到的效果就是LED在闪烁了,1秒闪烁一次
while(1)
        {
                LED = 1;//   pc13口
                delay_ms(500);   //延时500毫秒
                LED = 0;
                delay_ms(500);    //延时500毫秒
        }       


附:本课源码下载地址:http://pan.baidu.com/s/1eRWJTMa我去打游戏了,码字好累{:5_99:}

pk_小天 发表于 2017-7-5 09:01:07

还在学基础,顶一下~

kyowjw01 发表于 2017-7-12 10:32:08

表示能看懂。{:10_256:}

芒果沙冰 发表于 2017-7-23 17:51:42

太厉害楼主
页: [1]
查看完整版本: 圆梦那年3(c语言)---废话少说上干货