stm32c语言写数码管定时器,使用TIM1产生1秒定时控制数码管显示0-9(STM32_10)

一、项目配置

1、新建项目文件夹"TimSeg";

2、通过Keil5创建新项目,保存在所创建的文件夹中(设项目名为pTimSeg),选择MCU芯片为"STM32F103ZE"(本程序使用的硬件为:STM32-PZ6806L开发板)

3、在"TimSeg"文件夹下新建"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"文件夹。

① 在"CMSIS"文件夹中复制"core_cm3.h"和"core_cm3.c"文件;

② 在" Device "文件夹中复制"stm32f10x.h"、"system_stm32f10x.h"和"system_stm32f10x.c"文件;

③ 在" Startup "文件夹中复制"startup_stm32f10x_hd.s"文件;

④在"Lib"文件夹中新建"inc"和"src"两个子文件夹,在"inc"文件夹中复制"misc.h"、"stm32f10x_gpio.h"、"stm32f10x_tim.h"和"stm32f10x_rcc.h"文件;在"src"文件夹中复制"misc.c"、"stm32f10x_gpio.c"、"stm32f10x_tim.c"和"stm32f10x_rcc.c"文件;

4、为项目添加"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"组,并将上述C程序文件和"startup_stm32f10x_hd.s"启动文件加入到相应组中。

5、打开“项目配置”对话框,在"Output"选项卡中选择"Create HEX File",在"C/C++"选项卡中的"Include Paths"中添加如下包含路径:".CMSIS;", ".Device;", ".Libinc;",".Public;"。

6、在"stm32f10x.h"中添加函数参数检查宏

(参看:https://blog.csdn.net/fanxp66/article/details/80215090)

#ifdef  USE_FULL_ASSERT

/**

* @brief  这个assert_param宏用于函数参数检查

* @param  expr:如果expr是 false,就调用 assert_failed函数报告源文件名和

*         失败的行号,如果expr是 true ,就返回一个空值

* @retval None

*/

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

/* Exported functions ------------------------------------------------------- */

void assert_failed(uint8_t* file, uint32_t line);

#else

#define assert_param(expr) ((void)0)

#endif /* USE_FULL_ASSERT */

7、新建一个文件(system.h),保存到"Public"文件夹中,内容为:

#ifndef __SYSTEM__H

#define __SYSTEM__H

#include "stm32f10x.h"

//定义位带地址宏

#define BITBAND(addr,bitnum) ((addr&0xF0000000) + 0x02000000 + ((addr&0x000FFFFF)<<5) + (bitnum<<2))

#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

#define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))

//IO口地址映射

//数据输出寄存器地址

#define GPIOA_ODR_Addr          (GPIOA_BASE + 12)

#define GPIOB_ODR_Addr (GPIOB_BASE + 12)

#define GPIOC_ODR_Addr (GPIOC_BASE + 12)

#define GPIOD_ODR_Addr          (GPIOD_BASE + 12)

#define GPIOE_ODR_Addr (GPIOE_BASE + 12)

#define GPIOF_ODR_Addr (GPIOF_BASE + 12)

#define GPIOG_ODR_Addr          (GPIOG_BASE + 12)

//数据输入寄存器地址

#define GPIOA_IDR_Addr  (GPIOA_BASE + 12)

#define GPIOB_IDR_Addr  (GPIOB_BASE + 12)

#define GPIOC_IDR_Addr  (GPIOC_BASE + 12)

#define GPIOD_IDR_Addr  (GPIOD_BASE + 12)

#define GPIOE_IDR_Addr   (GPIOE_BASE + 12)

#define GPIOF_IDR_Addr   (GPIOF_BASE + 12)

#define GPIOG_IDR_Addr  (GPIOG_BASE + 12)

#endif

该文件定义了GPIO端口位带操作的宏。

二、数码管电路与使用配置

开发板上数码管相关电路如下图所示:

75681e5ab41d6f67d2521552718f2ffc.png

b782df3ce4205c28a13304665b75a0a6.png

要使得数码管正常显示需要进过以下步骤:

1、使能GPIOC时钟

2、配置GPIOC_0-GPIOC_7为推挽输出,50MHz速度

3、通过库函数操作控制输出

4、实现过程

① 在上述配置的项目中添加"seg.h"和"seg.c"文件,保存在"User/Seg"文件夹下,"seg.h"文件的内容为:

#ifndef __SEG__H

#define __SEG__H

#include "system.h"

#include "stm32f10x_gpio.h"

#define SEGPORT GPIOC

#define SEG_RCCPORT RCC_APB2Periph_GPIOC

#define SEGPIN (GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)

void Seg_Init(void);

#endif

"seg.c"文件的内容为:

#include "seg.h"

#include "stm32f10x_rcc.h"

void Seg_Init()

{

GPIO_InitTypeDef GPIOC_mode;

RCC_APB2PeriphClockCmd(SEG_RCCPORT, ENABLE);

GPIOC_mode.GPIO_Pin = SEGPIN;

GPIOC_mode.GPIO_Speed = GPIO_Speed_50MHz;

GPIOC_mode.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(SEGPORT, &GPIOC_mode);

}

void Show()

{

static u8 n=0;

u16 seg[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

GPIO_Write(SEGPORT, seg[n]);

n++;

n = n%10;

}

② 将"seg.c"文件添加到项目的"User"组中;

③ 将"./User/Seg"路径添加到项目文件包含的配置路径中(在"C/C++"选项卡中的"Include Paths"中)。

三、定时器TIM1配置

c35038859167111cc1dab5eab63cf444.png

1、选择定时器

使用定时器首先要选择定时器,stm32f103zet6MCU芯片有8个定时器,其中TIM1和TIM8称为高级定时器,TIM2-TIM5称为通用定时器,TIM6和TIM7称为基本定时器,这里选择TIM1作为通用定时器功能使用。

2、计算定时器配置参数

在本程序中,想要通过TIM1进行1秒的定时,实现每秒钟产生一次定时计数溢出中断,然后在中断函数中调用数码管显示输出。由于系统初始化时钟(调用SystemInit函数)后APB2总线上的时钟为72MHz,本程序中TIM1的时钟选择为CK_INT,为72MHz,这个频率进过预分频和计数后得到1秒的定时,需要设置预分频系数与定时计数值之积为72M,这里设置预分频系数为7200,计数器计数值为10000。

3、计数器配置编程

① 使能TIM1时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE );

② 配置TIM1参数

typedef struct

{

uint16_t TIM_Prescaler;         /*预分频系数. 取值0x0000-0xFFFF */

uint16_t TIM_CounterMode;       /*计数模式*/

uint16_t TIM_Period;            /*计数值 0x0000到 0xFFFF.  */

uint16_t TIM_ClockDivision;     /*!时钟分割,用于数字滤波器*/

uint8_t TIM_RepetitionCounter;  /*重复次数,仅对TIM1和TIM8有意义.

} TIM_TimeBaseInitTypeDef;

计数模式定义:

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)

#define TIM_CounterMode_Down               ((uint16_t)0x0010)

#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)

#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)

#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)

时钟分割

#define TIM_CKD_DIV1                       ((uint16_t)0x0000)

#define TIM_CKD_DIV2                       ((uint16_t)0x0100)

#define TIM_CKD_DIV4                       ((uint16_t)0x0200)

程序如下:

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;      //定义配置结构体变量

TIM_TimeBaseStructure.TIM_Prescaler = (7200– 1);

TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = (10000 –1);

TIM_TimeBaseStructure.TIM_ClockDivision =0;

TIM_TimeBaseStructure.TIM_RepetitionCounter= 0;

TIM_TimeBaseInit( TIM1,&TIM_TimeBaseStructure);

③ 设置定时器中断类型,并使能。

TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

④ 开启计数器,开始计数

TIM_Cmd( TIM1, ENABLE);

4、实现步骤

① 在上述配置的项目中添加"tim.h"和"tim.c"文件,保存在"User/Tim"文件夹下,"tim.h"文件的内容为:

#ifndef __TIM__H

#define __TIM__H

#include "system.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_tim.h"

void Init_Tim(void);

#endif

"tim.c"文件内容为:

#include "tim.h"

void Tim_Init(void)

{

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     //定义配置结构体变量

RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE );//使能定时器TIM1时钟

TIM_TimeBaseStructure.TIM_Prescaler = (7200-1);

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = (10000-1);

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit( TIM1, &TIM_TimeBaseStructure);

TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清除TIM1溢出中断标志

TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//打开溢出中断

TIM_Cmd( TIM1, ENABLE);       //启动定时器

}

② 将"tim.c"文件添加到项目的"User"组中;

③ 将"./User/Tim"路径添加到项目文件包含的配置路径中(在"C/C++"选项卡中的"Include Paths"中)。

四、NVIC配置和中断函数

1、配置中断分组(NVIC)

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

2、使能中断

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel =TIM1_UP_IRQn;     //定时器1上溢中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;       //主优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;

NVIC_Init( & NVIC_InitStructure);

3、实现步骤

① 在上述配置的项目中添加"nvic.h"和"nvic.c"文件,保存在"User/Nvic"文件夹下,"nvic.h"文件的内容为:

#ifndef __NVIC__H

#define __NVIC__H

#include "stm32f10x.h"

#include "misc.h"

void My_NVIC_Init(void);

#endif

"nvic.c"文件内容为:

#include "nvic.h"

void My_NVIC_Init(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2 );

NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;     //定时器TIM1上溢中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //主优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init( & NVIC_InitStructure);

}

② 将"nvic.c"文件添加到项目的"User"组中;

③ 将"./User/Nvic"路径添加到项目文件包含的配置路径中(在"C/C++"选项卡中的"Include Paths"中)。

五、主函数和终端服务函数

在main.c中添加中断服务函数TIM1_UP_IRQHandler,修改主函数,内容如下:

#include "seg.h"

#include "tim.h"

#include "nvic.h"

int main()

{

Seg_Init();

My_NVIC_Init();

Tim_Init();

Show();

while(1)

c2c9ed493cd281aa86d8a6f5178c4c01.gif [1] [2] 610626052e95c7fbe3d254abc769d9ad.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551078.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

for循环c语言流水灯,巧用数组与for循环为流水灯程序瘦身

数组——一种储存大量同性质数据的连续存储器空间a [6];b [] {2&#xff0c;4&#xff0c;8&#xff0c;3&#xff0c;6};c[6] {1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6};char d[6] "hello";以上方式均是数组创建的常用方式~数组是从…

java的map 使用string数组多了双引号_奥奥奥利给!!!再也不怕面试官问我String源码了!来吧...

简述字符串广泛应用 在 Java 编程中&#xff0c;在 Java 中字符串属于对象&#xff0c;Java 提供了String 类来创建和操作字符串。字符串缓冲区支持可变字符串。因为String对象是不可变的&#xff0c;因此可以共享它们。String类代表字符串&#xff0c;Java程序中的所有字符串字…

C 语言 运算符怎么使用,详解C++编程中运算符的使用

C的运算符十分丰富&#xff0c;使得C的运算十分灵活方便。例如把赋值号()也作为运算符处理&#xff0c;这样&#xff0c;abc4就是合法的表达式&#xff0c;这是与其他语言不同的。C提供了以下运算符&#xff1a;算术运算符(加) -(减) *(乘) /(除) %(整除求余) (自加) --(…

面积积分_袁颖妍:用定理积分求平面区域面积(有代表性的9个例题)

考研竞赛智慧e数学的广告&#xff1a;鸡汤所谓“理解”&#xff0c;所谓“智商”&#xff0c;本质上最终都归到"记忆",还有一点就是能够发现自己“记忆”中各个零散的知识点的关系。所谓“智商”高低的人&#xff0c;其实是强化这些“记忆”的能力的不同&#xff0c;…

字体选择_十分钟带你掌握精准选择字体的方法!

文章序言&#xff1a;上次记得有粉丝评论需要讲讲字体&#xff0c;今天就给大家带来一期关于&#xff0c;如何快速选择合适的字体的文章&#xff0c;帮助大家以后把字体用对&#xff0c;用好&#xff0c;用准。在讲这个字体的时候会结合实际的案例操作给大家讲解&#xff0c;这…

android自动生成cardview,学习使用Material Design控件(三)使用CardView实现卡片效果...

本文主要介绍CardView的使用&#xff0c;CardView是继承自FrameLayout&#xff0c;使用比较简单&#xff0c;只需要用CardView包含其他View就可以实现卡片效果了。实现效果如下&#xff1a;加入依赖库dependencies {….compile com.android.support:cardview-v7:22.2.0}Layout布…

android最新设计规范,Android应用未来的设计规范

谷歌在2014 I/O大会上不但发布了Android L&#xff0c;还一同推出了全新的Material Design设计语言&#xff0c;它被认为是未来Android系统和应用的设计方向。虽然Android L和谷歌自家的应用都会按照这一设计规范来执行&#xff0c;但第三方应用却没能够积极的响应。究竟用Mate…

移除apt源_apt提示处理归档 (--unpack)时出错的解决办法

#apt##Ubuntu##Debian#1、问题现象今天在升级软件的时候遇到一个错误&#xff0c;如下:rootx:~# apt --fix-broken install正在读取软件包列表... 完成正在分析软件包的依赖关系树 正在读取状态信息... 完成 正在修复依赖关系... 完成下列软件包是自动安装的并且现…

android 滑动接听源码,android仿摩拜单车APP、炫酷RecyclerView、卡片滑动、仿饿了么点餐、自定义索引等源码...

Android精选源码Android优质博客前言permissions4m 最初的设计是仅仅做成一个编译器注解框架&#xff0c;在1.0.0版本时&#xff0c;它纯粹地实现了原生 Android 请求流程&#xff0c;关于它的设计思路可以查看这篇如何打造一个 Android 编译时注解框架。但是当投入笔者自己项目…

zip版mysql5.6_mysql 5.6 压缩包版安装方法

Mysql安装的时候可以有msi安装和zip解压缩两种安装方式。zip压缩包解压到目录&#xff0c;要使用它还需对它进行一定的配置。下面对Mysql压缩包版的安装方法进行详细的描述&#xff0c;要是此文有不正确的认识&#xff0c;希望大家指正&#xff0c;非常感谢。一、下载mysql压缩…

鸿蒙系统 产品,华为首款鸿蒙系统产品成行业公敌!只因开机无广告:遭十大品牌批评...

【4月6日讯】随着荣耀30s手机正式发布&#xff0c;全新的麒麟820处理器也是再次给我们带来了巨大惊喜&#xff0c;毫无疑问&#xff0c;麒麟820处理器将会继续继承麒麟810处理器的“神U”特质&#xff0c;成为5G网络时代的新一代中端“神U”&#xff0c;但在荣耀30s发布会上&am…

html在线摄像头,在HTML里加载摄像头的方法

效果图&#xff1a; 整体效果:视频加载&#xff1a;拍照&#xff1a;第一步&#xff1a;创建HTML元素首先&#xff0c;我们要创建一个HTML5的文档。无标题文档然后在插入以下代码&#xff1a;截图第二步&#xff1a;创建JavaScript首先&#xff0c;要在里创建一个JavaScript&am…

mysql怎样实现先判断后联合_MYSQ创建联合索引,字段的先后顺序,对查询的影响分析...

MYSQ创建联合索引&#xff0c;字段的先后顺序&#xff0c;对查询的影响分析前言对于联合索引我们知道&#xff0c;在使用的时候有一个最左前缀的原则&#xff0c;除了这些呢&#xff0c;比如字段放置的位置&#xff0c;会不会对索引的效率产生影响呢&#xff1f;最左匹配原则联…

上海事业编制 计算机 待遇怎么样,事业单位情况

2010-09-12我们在公路系统工作&#xff0c;用工单位是事业单位编制&#xff0c;由上级部门批准招录下达指标。由于单位缺人&#xff0c;单位临时招录我们(不带指标)&#xff0c;我们已工作八年&#xff0c;自2003-2009一直签订合同&#xff0c;2009年到期后至今未签订合同&…

如何修改操作系统运行服务器,如何设置Bios 最常见bios设置与修改详细图解教程...

平时我们在使用计算机的时候一般很少会接触到BIOS&#xff0c;很多人都是在安装操作系统时才接触到的&#xff0c;因为在使用光盘安装系统时需将计算机的BIOS设置为从光驱启动&#xff0c;在重装系统、设置硬盘模式以及一些特殊情况都需要进入bios里面&#xff0c;进行相关设置…

mysql 回滚失败_Mysql非事务表回滚失败的现象

执行ROLLBACK(回滚)时&#xff0c;如果收到下述消息&#xff0c;表示事务中使用的1个或多个表不支持事务&#xff1a; 警告&#xff1a;某些更改的非事务性表不能被回滚。 这些非事务性表不受ROLLBACK语句的影响。 如果在事务中意外地混合了事务性表和非事务性表&#xff0c;导…

mysql连表查询on条件_mysql 外连接的时候,条件在on后面和条件在where后面的区别...

最近使用mysql的时候碰到一个问题&#xff1a;当一个表外联另一个表的时候&#xff0c;将一些查询条件放在on后面和放在where后面不太一样&#xff1a;学生分数表stuscore&#xff1a;当查询语句如下(查询语句1)&#xff1a;SELECT a.name,a.subject,a.score,a.stuid ,b.name,b…

应运ajax的几种语言,Ajax指的是什么

Ajax指的是什么发布时间&#xff1a;2020-08-05 14:18:52来源&#xff1a;亿速云阅读&#xff1a;103作者&#xff1a;小新这篇文章将为大家详细讲解有关Ajax指的是什么&#xff0c;小编觉得挺实用的&#xff0c;因此分享给大家做个参考&#xff0c;希望大家阅读完这篇文章后可…

oracle 数据导入 mysql_oracle数据库导出和oracle导入数据的二种方法(oracle导入导出数据)...

这篇文章主要介绍了oracle导入导出数据的二种方法&#xff0c;利用PL/SQL Developer工具导出和利用cmd的操作命令导出的出方法&#xff0c;大家参考使用吧方法一&#xff1a;利用PL/SQL Developer工具导出&#xff1a;菜单栏---->Tools---->Export Tables&#xff0c;如下…

iphone文件怎么上传到服务器,iPhone编程中文件上传到HTTP服务器

宝慕林4294392下面的代码使用HTTPPOST将NSData发布到Web服务器。您还需要一些PHP方面的知识。NSString *urlString "http://yourserver.com/upload.php";NSString *filename "filename";request [[[NSMutableURLRequest alloc] init] autorelease];[requ…