导航:首页 > 操作系统 > idr单片机

idr单片机

发布时间:2024-05-23 11:20:30

A. 学习MCS-51(具体以89C51为例)系列单片机的体会

http://www.38xian.com/index.aspx?menuid=4&type=articleinfo&lanmuid=19&infoid=685&language=cn

http://www.38xian.com/index.aspx?menuid=4&type=articleinfo&lanmuid=19&infoid=686&language=cn

又来看了一下,修改一下吧,加点文字

C语言学习总结
搞嵌入式的,大都用C语言写代码,本人从事单片机开发,也写了不少的代码,一直习惯用 if 、switch打天下,在定义数据结构的时候也只用到 字符型、整型、数组,位;很少用结构体,共用体,枚举,因为咱C语言学得不好,和它们不熟,总感觉它们不那么好招呼,重要的是自已觉得没必要用上它们。随着越来越多的积累,咱写代码的风格也在不断的发生变化,从以前的喜欢将所有的函数及数据的定义写在一个文件里到逐渐的将函数按功能模块化、从以前的习惯直接在程序里写常数到慢慢的开始用上宏来代替,咱编程的风格也逐渐开始正规化,编程水平也逐步提升,当然这些成绩都源于咱不断的学习,学习匠人的编程规范、学习herald的感悟设计、还有网上写得非常出色的代码以及STM32的固件函数库,在咱的不断领悟和思考下,总结了几点关于C语言的用法,与大家共同分享。

一、 学习匠人的头文件包含巧妙用法
当一个头文件被多个C文件包含,且该头文件中定义了这些C文件的公共变量,则在编译的时候会出现重复定义,导致编译通不过,通常我们会采用如下两种做法来解决上述问题。
(为了让问题表述得更清楚,我们假设两个C文件C1,C2,C3,一个头文件H1,C1,C2,C3有两个公共变量V1和V2)
1、 在C1文件中定义变量V1和V2,在C2和C3文件中对V1,V2用extern声明;
2、 在C1文件中定义变量V1和V2,在H1中对V1,V2用extern声明,然后在C2和C3文件中包含H1;
很显然,以上两种方法都要对V1和V2书写至少两次,一次定义,一次外部声明,且不是在同一文件下,这样不利于管理和修改,有没有一种方法可以让这些公用的变量放在一个文件里,且只要书写一次呢?
偶在二姨那里无意中看到匠人的发帖,就是关于该问题的讨论,现在我转发一下,与大家同共分享。首先我们将要用到的公共变量全部书写到com.h文件中,每一个变量在定义前加一个符号EXT_,当该头文件被main.c函数包含时,定义EXT_为空,表示com.h中的变量在main.c中被定义,当被其它文件包含时,定义EXT_为extern,表示外部声明,如:
Com.h文件:
//避免重复定义
#ifdef root
#define EXT_
#else
#define EXT_ extern
#endif

//全局变量
EXT_ u8 variable1; //该变量在三个C文件中都要用到

Main.c
#define root //在包含com.h前定义root
#include "com.h"

二、 用结构体的方式来定义总线或外设地址
当一个整体包含不同类型的多个成员时,通常用结构体来定义结构体变量,这样内存会将这些变量按照递增的方式分配到相邻的地址(不对齐的地方会有填充),按“结构体名.成员名”的方式访问结构体内的成员,这是访问结构体变量的方式;但是还有一种指向结构体变量的指针,它可以将某个地址转换成该结构体类型的指针,比如寄存器的定义:
(以下是摘自STM32固件函数库,关于GPIO的定义)
typedef struct
{
vu32 CRL; //0
vu32 CRH; //偏移量4
vu32 IDR; //偏移量8
vu32 ODR;
vu32 BSRR;
vu32 BRR;
vu32 LCKR;
} GPIO_TypeDef;

#define GPIOA_BASE ((u32)0x40010800) //GPIOA的基地址为0x40010800
#define GPIOA (GPIO_TypeDef *) GPIOA_BASE; //强制类型转换为GPIO_TypeDef类型的指针

这样在操作GPIOA的寄存器时只要这样写就可以了
读: X="GPIOA-">CRL; 写:GPIOA->CRL=X;
或 读: X=(*GPIOA).CRL; 写:(*GPIOA).CRL =X;

当然,要达到上述目的也可以采用如下方式
#define GPIOA_ CRL 0x40010800
#define GPIOA_ CRH 0x40010804
#define GPIOA_ IDR 0x40010808
#define GPIOA_ ODR 0x4001080C
#define GPIOA_ BSSR 0x40010810
#define GPIOA_ LCKR 0x40010814

很明显,第一种书写方式更加正规化,且当定义多个GPIO时,只要将其它GPIO的基地址强制转换为该结构类型的指针即可。

再来看看一个定义外部总线的例子
typedef struct
{
vu8 CH375_DATA;
vu8 CH375_CMD; //偏移量1
} CH375_TypeDef;
#define CH375 ((CH375_TypeDef *) 0x6c000000)
CH375-> CH375_DATA=data; //往0x6c000000地址处写数据
CH375-> CH375_CMD=cmd; //往0x6c000001地址处写命令
怎么样,是不是方便多了。重要的是代码的观赏和可读性提高了。

三、 用枚举数据类型来定义特定的状态
在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个函数在操作过程中会返回几个特定的状态:操作成功,操作失败,忙,等等。如果我们直接在函数里用0,1和2来表示这三种状态,有时偶尔会出现数值与实际状态对不上号的情况,造成置状态和判断状态错误,那么我们可以在程序里用宏或者枚举来事先定义好这些状态。
如:用宏定义:
#define Sucess 0
#define Failure 1
#define Busy 2

用枚举
typedef enum { Sucess = 0, Failure , Busy } FlagStatus;

四、 用共用体类型定义共享内存空间
共用体类型定义的数据是将多个成员共享同一内存空间,该空间的大小为最大成员的大小,其用法与结构体完全相同,但值得注意的是不能同时引用多个成员,在某一时刻只能使用其中之一成员。
在程序中如果全局变量比较多,包含几个结构和数组,如果这些全部定义的话势必会占大量的内存,有可能还会导致单片机内存不够,如果能让几个不同时用到的数组和结构变量共享一段内存,则能省出很多的内存空间。
比如以下输入输出若不同时进行,则可以共享同一段内存空间
union {
struct {
unsigned char Flag;
unsigned char Type;
unsigned char State;
unsigned long DataLen;
unsigned char Buffer[64];
}DataOut;
struct {
unsigned char Flag;
unsigned char Type;
unsigned char State;
unsigned long DataLen;
unsigned char Buffer[64];
} DataIn;
} BOC;

C语言博大精深,丰富多彩,用得好能很好的发挥它的作用,同时学习好的编程方法养成良好的编程习惯对于一名设计人员来说也是极其的重要,以上四点都是本人自身积累和学习的一些总结,希望能够与大家一起共同交流,共同学习和提高。

个人珍藏的好文章,贴出来分享

B. stm8s鍗旷墖链鸿籭o鍙g数骞虫庝箞楗挎搷浣

a=PB_IDR&0x01;

C. STM8S103K3,ST的8位单片机,寄存器的位操作

在IAR里面先是用了结构体struct的位域定义一个字节的八位,然后再用联合体union定义两个变量,一个unsigned char NAME用于全局操作,一个BIT_STRUCT NAME ## _bit用于位操作。如果还不明白,请先了解结构体与联合体。

D. stm32 C语言特殊性

这是标准的C语言啊,不是STM32的特殊用法,你那个写的是对的,相当于:

((int *) 0x00000000) = 1;

这么个意思;

那么为什么要用结构体呢?
不是C语言的特殊用法,是因为STM32这种单片机的外设架构,STM32把所有同类型的外设集中到了一块,这样库就好写多了。
太详细我也说不明白,给你举个例子吧:

比如说,我是说比如啊,GPIOA的CRL寄存器地址是0,CRH寄存器地址是4,IDR寄存器地址是8,ODR寄存器地址是12,那么,按照你刚才的写法是

#define GPIOA_CRL *((unsigned long*)(0x00000000))
#define GPIOA_CRH *((unsigned long*)(0x00000004))
#define GPIOA_IDR *((unsigned long*)(0x00000008))
#define GPIOA_ODR *((unsigned long*)(0x0000000C))

如果用结构体,就方便多了
typedef struct
{
vu32 CRL;
vu32 CRH;
vu32 IDR;
vu32 ODR;
vu32 BSRR;
vu32 BRR;
vu32 LCKR;
} GPIO_TypeDef;

GPIO_TypeDef *GPIOA = (GPIO_TypeDef *)(0x00000000);
这样一写,那么,就注定了GPIOA->CRL 的地址肯定是0;
GPIOA->CRH的地址肯定是4;
GPIOA->IDR的地址肯定是8;
比你那样写省事了不少吧?

E. PIC单片机编程软件

KEIL没办法编译PIC的任何单片机的程序
用PIC单片机生产商MICROCHIP公司自己推出的MPLAB ide软件开发程序,免费的。
但这个软件默认安装的没有C编译器(默认的只能编译汇编文件)。你还得去Microchip那里下载PICC for PIC18(HI-TECH公司做的,这公司被MICROCHIP收购了),或者是Microchip公司自己开发MPLAB C18编译器。这些编译器安装后自动嵌入到MPLAB内部。
反正这两个都是收费的(最便宜的PICC买800rmb)。但网上有很多关于他们的破解版

F. STM32涓娆℃ц诲彇32浣嶆寜阌镄勫

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);//搴撴柟寮
uint16_t KeyH=GPIOx->IDR;//鐩存帴镎崭綔瀵勫瓨鍣
璇诲彇鏁翠釜GPIOX镄勮緭鍏ョ姸镐併

瑕佹槸闇瑕佽诲叆涓や釜GPIO绔鍙g殑鐘舵佺殑璇濓纴鍏埚垎鍒璇诲彇绔鍙g姸镐佸瓨鍒板彉閲忎腑锛屼箣钖庤繘琛屾暟鎹澶勭悊鍗冲彲銆

G. STM8单片机中,DDR .ODR.IDR是什么呀,51程序中都没有写到这些。

DDR是方向寄存器,值为0时IO口输入,为1时IO口输出。
ODR是输出寄存器,当IO口在输出状态下时,ODR值为0则输出低电平,为1输出高电平。
IDR是输入寄存器,IO口在输入模式下,会因外设的状态改变而产生高低电平,读取电平的高低可判断外设的变化;比如计时到一定程度,电平变低(为0),单片机读取IDR值为0,就知道计时达到某个点了。

阅读全文

与idr单片机相关的资料

热点内容
火柴人游戏源码 浏览:808
青海一机xk713数控铣床编程 浏览:50
分子遗传学pdf 浏览:406
区块链加密猫游戏 浏览:338
手机蓝牙怎么转移app 浏览:349
linux删除文件不提示 浏览:975
期货公式源码三角形 浏览:858
压缩大师手机版 浏览:401
单片机原理与应用c语言 浏览:523
源码编辑器如何上传音乐 浏览:249
哪里卖软件源码 浏览:152
怎么将软件做成手机app 浏览:21
pdf下载官方下载中文版 浏览:606
linux避免自动被终止命令 浏览:81
技能比赛网站源码 浏览:205
eclipse编译关了怎么开 浏览:988
脱单程序员 浏览:891
域名销售网站源码 浏览:79
云服务器性能高吗 浏览:693
9PQQ协议源码 浏览:824