大家好, 今天主要和大家聊一聊,如何利用C语言控制LED灯的实验。

目录

​第一:C语言板控制LED灯简介

第二:实验程序实现

​第三:C语言实验控制程序


​第一:C语言板控制LED灯简介

实际工作中很少会使用到汇编去编写嵌入式驱动,毕竟汇编太难,写出来也不好理解,大部分情况下都使用C语言去编写。只是在开始部分用汇编初始化一下C语言环境,比如初始化DDR、设置堆栈指针SP等。当这些工作都做完以后就可以进入C语言环境,也就是运行C语言代码,一般都是进入main函数。所以都是进入main函数,有两部分文件要做:

1、汇编文件

汇编文件只是用来完成C语言环境搭建的。

2、C语言文件

C语言文件就是完成我们的业务层代码的,其实就是我们实际要完成的功能。其实STM32也是这样的,只是我们在开发STM32的时候没有想到这一点,以STM32中启动文件startup_stm32f10x_hd.s这个汇编文件就是完成C语言环境搭建的,当然还有一些其他处理,比如中断向量表等。

第二:实验程序实现

在STM32中,启动文件startup_hd.s就是完成C语言环境搭建的,当然还有一些其他的处理。

 Stack_Size EQU 0x00000400                 AREA STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem SPACE Stack_Size __initial_sp; <h> Heap Configuration; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>; </h>Heap_Size EQU 0x00000200   AREA HEAP, NOINIT, READWRITE, ALIGN=3   __heap_base   Heap_Mem SPACE Heap_Size__heap_limit//省略掉部分代码Reset_Handler PROC    EXPORT Reset_Handler [WEAK]    IMPORT __main    IMPORT SystemInit    LDR R0, =SystemInit    BLX R0     LDR R0, =__main    BX R0    ENDP

代码分析:设置栈的大小,这里设置为0X400=1024字节。下面遇到的__initial_sp就是初始化SP指针。设置堆的大小,复位中断服务函数,STM32复位完成以后会执行中断服务函数。 调用SystemInit()函数来完成其他初始化工作,会调用__main是库函数实现。

.global _start /* 全局标号 */_start:/* 进入 SVC 模式 */ mrs r0, cpsr bic r0, r0, #0x1f /* 将 r0 的低 5 位清零,也就是 cpsr 的 M0~M4 */ orr r0, r0, #0x13 /* r0 或上 0x13,表示使用 SVC 模式 */ msr cpsr,r0       //将r0的数据写入到cpsr_c中    ldr sp, =0X80200000 /* 设置栈指针 */ b main /* 跳转到 main 函数 */

这里我们可以设置处理器运行于SVC模式下,处理器模式的设置是通过修改CPSR程序状态寄存器来完成的。上面编写的start.s文件中却没有初始化DDR3的代码,但是却将SVC模式下的SP指针设置到了DDR3的地址范围中,这不会出问题吗?肯定不会的,DDR3肯定还是要初始化的,DCD数据包含了DDR配置参数,内部的Boot ROM会读取DCD数据中的参数完成DDR初始化的。

​第三:C语言实验控制程序

C语言部分有两个文件件 main.c 和 main.h,main.h 里面主要是定义的寄存器地址,在 main.h 里面输入代码:

#ifndef __MAIN_H#define __MAIN_H//CCM相关寄存器地址#define CCM_CCGR0 *((volatile unsigned int *)0X020C4068)#define CCM_CCGR1 *((volatile unsigned int *)0X020C406C)#define CCM_CCGR2 *((volatile unsigned int *)0X020C4070)#define CCM_CCGR3 *((volatile unsigned int *)0X020C4074)#define CCM_CCGR4 *((volatile unsigned int *)0X020C4078)#define CCM_CCGR5 *((volatile unsigned int *)0X020C407C)#define CCM_CCGR6 *((volatile unsigned int *)0X020C4080)//相关寄存器地址#define SW_MUX_GPIO1_IO03 *((volatile unsigned int *)0X020E0068)#define SW_PAD_GPIO1_IO03 *((volatile unsigned int *)0X020E02F4)//GPIO1相关寄存器地址 #define GPIO1_DR *((volatile unsigned int *)0X0209C000) #define GPIO1_GDIR *((volatile unsigned int *)0X0209C004) #define GPIO1_PSR *((volatile unsigned int *)0X0209C008) #define GPIO1_ICR1 *((volatile unsigned int *)0X0209C00C) #define GPIO1_ICR2 *((volatile unsigned int *)0X0209C010) #define GPIO1_IMR *((volatile unsigned int *)0X0209C014) #define GPIO1_ISR *((volatile unsigned int *)0X0209C018) #define GPIO1_EDGE_SEL *((volatile unsigned int *)0X0209C01C) #endif

在main​.h中以宏定义的形式定义要使用到所有的寄存器,后面的数字就是其地址信息,比如CCM_CCGR0 寄存器的地址就是 0X020C4068,这个很简单,很好理解。main.c函数的具体实现​。

#include "main.h"//使能外设的所有时钟void clk_enable(void){ CCM_CCGR0 = 0xffffffff; CCM_CCGR1 = 0xffffffff; CCM_CCGR2 = 0xffffffff; CCM_CCGR3 = 0xffffffff; CCM_CCGR4 = 0xffffffff; CCM_CCGR5 = 0xffffffff; CCM_CCGR6 = 0xffffffff; }  //初始化LED对应的GPIO时钟 void led_init(void) {    /* 1、初始化 IO 复用, 复用为 GPIO1_IO03 */     SW_MUX_GPIO1_IO03 = 0x5;        //配置GPIO1_IO03属性     SW_PAD_GPIO1_IO03 = 0X10B0;        //初始化GPIO,GPIO_IO03设置为输出     GPIO1_GDIR=0X0000008;        //设置GPIO1_IO03输出低电平,打开LED0      GPIO1_DR = 0x0; }  //打开对应的LED灯 void led_on(void) {   //将GPIO1_DR 的 bit3 清零    GPIO1_DR &= ~(1<<3); }  //关闭LED灯 void led_off(void) {     GPIO1_DR |= (1<<3); }  //短暂的延时函数 void delay_short(volatile unsigned int n) {    while(--){} }  //延时大约1ms的函数 void delay(volatile unsigned int n) {     while(n--)     {       delay_short(0x7ff);     } }  int main(void) {     clk_enable(); /* 使能所有的时钟 */     led_init(); /* 初始化 led */         while(1) /* 死循环 */ {     led_off(); /* 关闭 LED */    delay(500); /* 延时大约 500ms */      led_on(); /* 打开 LED */    delay(500); /* 延时大约 500ms */ }     return 0; }

利用Makefile文件可以进行编译,将对应的可执行文件,放到开发板上,可以看到LED大概500ms闪烁一次​。

​总结:利用C语言实现底层驱动的控制,要注意可执行程序放的位置,以及如何链接编译等​。

Linux系统中利用C语言控制LED的方法相关推荐

  1. Linux 系统中利用 apt-get 管理软件的安装目录和安装路径

    Linux 系统中利用 apt-get 管理软件的安装目录和安装路径 apt-get 下载软件存放路径: /var/cache/apt/archives lib 文件路径: /usr/lib 可执行文 ...

  2. Linux系统中运行.sh文件的几种方法

    在Linux系统中执行.sh文件的几种方法: 1. cd到.sh文件所在的目录,然后执行./xxx.sh   [前提:该./sh文件要有可执行的权限,chmod u+x xxx.sh]  2. 在任何 ...

  3. linux系统下定时备份,在Linux系统中简单地实现定时备份的方法 -电脑资料

    运行一个简单的脚本 假设你有一个脚本叫:/usr/local/bin/myscript. ,你想要每隔一小时就运行一次, Service 文件 第一步,创建一个service文件,根据你Linux的发 ...

  4. linux系统中清空文件内容的三种方法

    1.使用vi/vim命令打开文件后,输入"%d"清空,后保存即可.但当文件内容较大时,处理较慢,命令如下: vim file_name :%d :wq 2.使用cat命令情况,命令 ...

  5. 虚拟机linux gedit,Linux系统中把gedit改造成TextMate的方法

    TextMate是一款轻量级的文本编辑器软件,它具有出色的界面和强大的功能,能够提升开发者的编码效率.这款软件也开放源代码了,但是只能在Mac OS X上使用,因此小编下面给大家介绍一个方法,能够把g ...

  6. linux 终端交换caps,linux系统中ctrl和capslock键互换的方法

    今天这篇教程我们来为大家介绍一下,linux系统中ctrl和capslock键互换的方法,有兴趣的朋友就来参考一下吧. 1.首先,点击任务栏上的"启动器". 2.在"启动 ...

  7. 在Linux系统中运行C语言程序

    正式学习c语言的第一天   2022/1/10 在之前的学习中已经在Windows系统中用Microsoft VC++上实现了C语言程序的运行,现在将在Linux系统上运行C语言程序. 首先明确C语言 ...

  8. linux所请求的操作需要超级用户权限,详解Linux系统中的root权限控制

    在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户 ...

  9. 在Linux系统中存储设备的两种表示方法

    作者:北南南北 来自:LinuxSir.Org 摘要: 硬盘和硬盘分区在Linux都表示为设备,按我们通俗的说法来说,就是怎么来表示或描述硬盘和或硬盘分区,但这种描述应该是科学和具体的:比如IDE硬盘 ...

最新文章

  1. c语言 char转int_C语言关键字及进制的转换你都知道吗?
  2. LTE voice centric和data centric
  3. server sql 判断是否是当天_判断sql server 是否在开启服务状态
  4. 集合已修改,可能无法执行枚举操作
  5. 千位分隔符转换为数字
  6. 对几种传递的理解:值传递,地址传递,引用传递
  7. 机器学习中的数学——激活函数(一):Sigmoid函数
  8. 百胜中国供应链管理中心正式开工落户上海嘉定;百度发布第六代量产无人车 | 美通企业日报...
  9. mount: unknown filesystem type
  10. js获取注册表中应用程序的路径,并通过注册表打开
  11. 华东师范大学2019计算机与软件工程学院 “高可信”夏令营总结
  12. python常用的颜色英文表达_python 中颜色的表示
  13. 《起跑吧,Opa》 -- 中译本 第一章 初识Opa
  14. HTML5Canvas实现简易画图工具(铅笔,直线,矩形,圆,文本框,橡皮擦等)
  15. C++转换函数 (conversion function)
  16. android 刘海机型适配,Android全面屏刘海适配
  17. 郑州机电工程学校计算机部,郑州机电工程学校2021年招生录取分数线
  18. MySQL 创建表时出现 Tablespace for `xxx`.`xxx` exists.
  19. php 连接已重置,[百思不得其解] Nginx 连接已重置 ERR_CONNECTION_RESET
  20. 达梦数据库(DM8)DCA培训及认证考试有感--附ODBC使用新场景

热门文章

  1. 基于Linux的Spark安装与环境配置
  2. 所有表单对象_【第十课】常见的表单
  3. 数据中心冷水机组案例浅析
  4. 计算机应用基础模拟试卷 一,计算机应用基础模拟试卷一模拟试卷-02answer
  5. java之封装,继承,多态
  6. COBOL学习之COMMIT--ROLLBACK
  7. 我的Java春季历程,思维导图+源代码+笔记+项目
  8. Python使用Reportlab处理PDF数据 - 图形和图表
  9. 思科静态路由和浮动路由的配置
  10. 优秀课件笔记之决策支持系统