OpenEdv-开源电子网

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

工作之余学习STM32验证原子哥例程

[复制链接]

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
发表于 2016-1-19 15:58:30 | 显示全部楼层 |阅读模式
工作2年了,自己画了个底板。借着原子哥的肩膀,一一验证学习下。有感悟将贴出来,大家一起讨论
原来你也在这里
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
135
金钱
135
注册时间
2015-11-8
在线时间
31 小时
发表于 2016-2-18 21:38:35 | 显示全部楼层
楼主程序写的很规范啊
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-25 15:36:29 | 显示全部楼层
/**********************************************************************************
* 文件名  :exit.c
* 硬件连接:-----------------
*          |   PA1 - EXTI1  |
*           ----------------
* 库版本  :ST3.5.0
* 作者    :大雄
* 时间    :2016-01-25
* 备注    :STM32所有IO口都可以配置成中端口
**********************************************************************************/
#include "exit.h"
#include "led.h"

//描述  :配置嵌套向量中断控制器NVIC
void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

#ifdef  VECT_TAB_RAM                                //根据预编译条件决定中断向量表起始地址
    NVIC_SetVectorTable(NVIC_VectTab_RAM , 0x0);    //中断向量表起始地址从 0x20000000 开始
#else         /* VECT_TAB_FLASH */
    NVIC_SetVectorTable(NVIC_VectTab_FLASH , 0x0);  //中断向量表起始地址从 0x80000000 开始   
#endif
        //所有 4 位用来配置抢占优先级
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //Group_0-4,中断优先级分组  抢占式优先级别设置为2位;响应优先级占2位

        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;           //开启 串口1 中断, 1级先占优先级,0级后占优先级  
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          //响应优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //其属性编号越小,表明它的优先级别越高
        NVIC_Init(&NVIC_InitStructure);       
       
        NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;          //开启外部中断,nRF信号接收中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);                 
}

void NRF24L01_Configuration(void)        //nRF使用的外部中断的引脚初始化
{
        GPIO_InitTypeDef GPIO_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

        //配置SPI_NRF_SPI的IRQ引脚
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_SetBits(GPIOA, GPIO_Pin_1);

        GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
       
        EXTI_InitStructure.EXTI_Line = EXTI_Line1;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        EXTI_ClearITPendingBit(EXTI_Line1);
}

//外部中断1服务程序
void EXTI1_IRQHandler(void)
{
        LED_EYE2_XOR;
        EXTI_ClearITPendingBit(EXTI_Line1); //清除LINE1上的中断标志位  
}
简单的中断测试

原来你也在这里
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-25 15:34:17 | 显示全部楼层
/**********************************************************************************
* 文件名  :led.c
* 硬件连接:-----------------
*          |   PB9 - LED-EYE1  |
*          |   PB8 - LED-EYE2  |
*          |   PB12- LED-B     |
*          |   PB13- LED-R     |
*          |   PB14- LED-G     |
*           -----------------
* 库版本  :ST3.5.0
* 作者    :大雄
* 时间    :2016-01-19
* 备注    :LED-B、LED-R、LED-G做七彩渐变用
**********************************************************************************/
#include "led.h"

void LED_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体

        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);//开启GPIOC的外设时钟
                                                                                                                          
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;//选择要控制的GPIOC引脚               
       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置引脚模式为通用推挽输出   
       
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚速率为50MHz  
       
          GPIO_Init(GPIOB, &GPIO_InitStructure);        //调用库函数,初始化GPIOC          
       
        GPIO_SetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14);        //关闭所有led灯
}

/**********************************************************************************
* 文件名  :led.h
* 硬件连接:-----------------
*          |   PB9 - LED-EYE1  |
*          |   PB8 - LED-EYE2  |
*          |   PB12- LED-B     |
*          |   PB13- LED-R     |
*          |   PB14- LED-G     |
*           -----------------
* 库版本  :ST3.5.0
* 作者    :DX
* 时间    :2016-01-14
* 备注    :读输入状态的IO口用GPIO_ReadInputDataBit,读输出状态的IO口用GPIO_ReadOutputDataBit
**********************************************************************************/
#ifndef __LED_H_
#define __LED_H_

#include "stm32f10x.h"

#define LED_EYE1_ON     GPIO_ResetBits(GPIOB,GPIO_Pin_9)
#define LED_EYE1_OFF    GPIO_SetBits(GPIOB,GPIO_Pin_9)
#define LED_EYE1_XOR    GPIO_WriteBit(GPIOB, GPIO_Pin_9,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_9))))//取反

#define LED_EYE2_ON     GPIO_ResetBits(GPIOB,GPIO_Pin_8)
#define LED_EYE2_OFF    GPIO_SetBits(GPIOB,GPIO_Pin_8)
#define LED_EYE2_XOR    GPIO_WriteBit(GPIOB, GPIO_Pin_8,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8))))//取反

#define LED_R_ON        GPIO_ResetBits(GPIOB,GPIO_Pin_13)
#define LED_R_OFF       GPIO_SetBits(GPIOB,GPIO_Pin_13)

#define LED_G_ON        GPIO_ResetBits(GPIOB,GPIO_Pin_14)
#define LED_G_OFF       GPIO_SetBits(GPIOB,GPIO_Pin_14)

#define LED_B_ON        GPIO_ResetBits(GPIOB,GPIO_Pin_12)
#define LED_B_OFF       GPIO_SetBits(GPIOB,GPIO_Pin_12)

#define LED_EYE_ALL_OFF GPIO_SetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9)// | GPIO_Pin_3 | GPIO_Pin_2)
#define LED_EYE_ALL_ON  GPIO_ResetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9)// | GPIO_Pin_3 | GPIO_Pin_2)

void LED_Configuration(void);

#endif


一般调试都用LED做指示用

原来你也在这里
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-25 13:49:26 | 显示全部楼层
/**********************************************************************************
* 文件名  :usart1.c
* 硬件连接:------------------------
*          | PB6  - USART1(Tx)      |
*          | PB7  - USART1(Rx)      |
*           ------------------------
* 库版本  :ST3.5.0
* 作者    :大雄
* 时间    :2016-01-19
* 备注    :开启串口DMA空闲中断接收不定长度数据,可返回该数据内容及长度
**********************************************************************************/
#include "usart1.h"

uint8_t USART1_RX_BUF[USART1_LENTH_BUF];//接收缓冲,最大64个字节
uint8_t USART1_TX_BUF[USART1_LENTH_BUF];//发送缓冲,最大64个字节
uint8_t FLAG_USART_RX = 0;              //接收到数据
uint8_t LENTH_USART_RX = 0;             //接收到数据的长度

void USART1_Configuration(uint32_t bound)//bound为波特率
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    DMA_InitTypeDef     DMA_Initstructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);//端口重映射
    //USART1_TX   PB6
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    //USART1_RX          PB7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);  

    //USART 初始化设置
    USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    DMA_Initstructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
    DMA_Initstructure.DMA_MemoryBaseAddr     = (uint32_t)USART1_RX_BUF;
    DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_Initstructure.DMA_BufferSize = 64;
    DMA_Initstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_Initstructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_Initstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_Initstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_Initstructure.DMA_Mode = DMA_Mode_Normal;
    DMA_Initstructure.DMA_Priority = DMA_Priority_High;
    DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel5, &DMA_Initstructure);

    DMA_Cmd(DMA1_Channel5,ENABLE);//启动DMA

    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  //若总线空闲,产生中断   
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);    //开启串口DMA接收

    USART_Cmd(USART1, ENABLE);                      //使能串口
    USART_ClearFlag(USART1, USART_FLAG_TC);         //清发送完成标志/////////////////////////////////////////////////////////////A
}

//重定向c库函数printf到USART1,由printf调用
int fputc(int ch, FILE *f)
{       
        USART_SendData(USART1, (unsigned char) ch);//将Printf内容发往串口
        while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);//检查串口发送是否完成的标志位TC       
        return (ch);
}

//输出单个字节
void USART1_PutChar(uint8_t Data)  
{  
    USART_SendData(USART1, Data);  
    while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );
}  

//输出数组
void USART1_PutStr(uint8_t *str, uint8_t Data_lenth)   
{   
    uint8_t i = 0;
    for (i = 0; i < Data_lenth; i++)   
    {      
        USART1_PutChar(*str);   
        str++;   
    }   
}

//串口1中断服务程序
void MY_USART1_IRQHandler(void)                       
{
    uint8_t i = 0;
    if(USART_GetITStatus(USART1, USART_IT_IDLE)==SET) { //空闲总线中断   
        i = USART1->SR;
        i = USART1->DR; //  ---待解/////////////////////////////////////////////////////////////B     

        DMA_Cmd(DMA1_Channel5, DISABLE);                //关闭DMA
        USART_ClearITPendingBit(USART1, USART_IT_IDLE); //清除中断标志
        USART_ITConfig(USART1, USART_IT_IDLE, DISABLE); //禁止中断,防止覆盖

        LENTH_USART_RX = 64 -  DMA_GetCurrDataCounter(DMA1_Channel5);   //得到真正接收数据个数  
        DMA1_Channel5->CNDTR = 64;      //重新设置接收数据个数   
        DMA_Cmd(DMA1_Channel5, ENABLE); //开启DMA
        FLAG_USART_RX = 1;              //接收数据标志位置1
        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  //再次开中断
    }   
}

main函数中调用
    while (1) {
        if(FLAG_USART_RX == 1) {        
            USART1_PutChar(LENTH_USART_RX);
            USART1_PutStr(USART1_RX_BUF, LENTH_USART_RX);
            FLAG_USART_RX = 0;LED_EYE2_XOR;
        }

    }

有2点需重视下,A处如果屏蔽了,则上电的时候串口输出会缺少第一个数据;B是我没能理解的,有看到的请帮助理解下,多谢了!

原来你也在这里
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-25 11:45:01 | 显示全部楼层
漆黑丨夜 发表于 2016-1-25 10:46
嗯,我最近使用了原子哥的delay程序,发现delay_us函数经常会卡死在do while循环中,移植想不通这是为什 ...

嗯,我补上us延时的误差吧。
空跑main,100us延时误差6us,20us延时误差2us,1us延时误差0.4us.
原来你也在这里
回复 支持 反对

使用道具 举报

10

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
157
金钱
157
注册时间
2016-1-21
在线时间
30 小时
发表于 2016-1-25 10:46:08 | 显示全部楼层
大雄先生 发表于 2016-1-20 09:21
倒序方便查阅最新动态。部分中断会影响Sys_Tick的运行,是指Sys_Tick被其他中断打断后恢复现场不完整,具 ...

嗯,我最近使用了原子哥的delay程序,发现delay_us函数经常会卡死在do while循环中,移植想不通这是为什么,看到楼主的贴,我就明白了。
请问一下楼主的延时us函数误差大不?
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-25 09:35:46 | 显示全部楼层
龙之谷 发表于 2016-1-20 12:01
倒序帖,哈哈,看回复一时没反应过来,思维定势了

单片机工作频率不同,同一条语句用时不同,同一外部 ...

额,是需要说明,一直只当默认,忘记了大家的环境不会和我一样,检讨。。
原来你也在这里
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-1-20 12:01:02 | 显示全部楼层
大雄先生 发表于 2016-1-20 09:09
多谢大神扶贴。实测空跑main,100ms延时误差2ms,5ms延时误差100us。另,频率,是指主频吗?用的是这颗 ...

倒序帖,哈哈,看回复一时没反应过来,思维定势了

单片机工作频率不同,同一条语句用时不同,同一外部晶振,配置72M和32M情况下软件延时不一样,所以需要对频率进行说明
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-20 09:21:05 | 显示全部楼层
emWin 发表于 2016-1-20 09:15
似乎是倒序的帖,不过楼主为了避免中断影响,你改为软延时,说得通吗?

倒序方便查阅最新动态。部分中断会影响Sys_Tick的运行,是指Sys_Tick被其他中断打断后恢复现场不完整,具体缘由还没有深入。以后要是透彻了,会贴出来,也欢迎有自己观点的留言
原来你也在这里
回复 支持 反对

使用道具 举报

18

主题

422

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1139
金钱
1139
注册时间
2014-5-24
在线时间
116 小时
发表于 2016-1-20 09:15:10 | 显示全部楼层
似乎是倒序的帖,不过楼主为了避免中断影响,你改为软延时,说得通吗?
I See Fire.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.  只给方向,不妨碍思考
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-20 09:09:18 | 显示全部楼层
龙之谷 发表于 2016-1-19 17:16
谢谢分享.....

大延时如100ms和小延时如5ms误差大概多少?另,软件延时要说明频率的哦


多谢大神扶贴。实测空跑main,100ms延时误差2ms,5ms延时误差100us。另,频率,是指主频吗?用的是这颗STM32F103C8T6/LQFP-48,8M晶振。受教了!
原来你也在这里
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2016-1-19 17:16:34 | 显示全部楼层
大雄先生 发表于 2016-1-19 16:55
/**********************************************************************************
* 文件名  :de ...

谢谢分享.....

大延时如100ms和小延时如5ms误差大概多少?另,软件延时要说明频率的哦
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

6

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
432
金钱
432
注册时间
2016-1-19
在线时间
38 小时
 楼主| 发表于 2016-1-19 16:55:16 | 显示全部楼层
/**********************************************************************************
* 文件名  :delay.c
* 硬件连接:无
* 库版本  :ST3.5.0
* 作者    :大雄
* 时间    :2016-01-19
* 备注    :系统的一些中断会影响systick的延迟函数,因此编写了普通延时,经示波器验证。
**********************************************************************************/
#include "delay.h"

void delay_ms(uint32_t ms)
{
        static uint32_t i;
        while(ms--) {       
                i = 2800;
                while(i--);
        }
}

void delay_us(uint32_t us)
{
        static uint32_t i = 0;
        while(us--) {       
                if(i != 1) {//加入if条件填充us时间
            i=1;
        }
                while(i--);               
        }
}
原来你也在这里
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-21 02:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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