快讯
HOME
快讯
正文内容
tacls nand 嵌入式开发中的C语言技巧你知道多少?
发布时间 : 2024-11-24
作者 : 小编
访问数量 : 23
扫码分享至微信

嵌入式开发中的C语言技巧你知道多少?

想学习单片机的同学可以关注、私信我或者在评论区回复我要入门。这一期我们来分享一下在嵌入式开发中常用的C语言技巧。看完这一篇文章,至少可以让你的C语言向前迈进一大步。

1.指向函数的指针

指针不单单是指向变量、字符串、数组,它还能够指向函数。在C语言中允许将函数的入口地址赋值给指针。这样就可以通过指针对函数进行访问。还可以把函数指针当成参数来传递。函数指针可以简化代码,减少修改代码的工作量。接下来我们通过一些具体的例子来了解一下。

/*函数指针简单讲解

*通过指向函数的指

*针调用比较两个数

*大小的程序

*/

#include

using namespace std;

/*比较函数声明*/

int max(int,int);

/*指向函数的指针声明(此刻指针未指向任何一个函数)*/

int (*test)(int,int);

int

main(int argc,char* argv[])

{

int largernumber;

/*将max函数的入口地址赋值给

*函数指针test

*/

test=max;

/*通过指针test调用函数max实

*现比较大小

*/

largernumber=(*test)(1,2);

cout<<><>

return 0;

}

int

max(int a,int b)

{

return (a>b?a:b);

}

通过上面这部分大家可以了解到函数指针其实和变量指针、字符串指针是大同小异的。如果大家理解了这个小程序,那么理解起下面这个有关Nand flash的源代码就会容易一些。

typedef struct {

void (*nand_reset)(void);

void (*wait_idle)(void);

void (*nand_select_chip)(void);

void (*nand_deselect_chip)(void);

void (*write_cmd)(int cmd);

void (*write_addr)(unsigned int addr);

unsigned char (*read_data)(void);

}t_nand_chip;

static t_nand_chip nand_chip;

/* NAND Flash操作的总入口,它们将调用S3C2410或S3C2440的相应函数 */

static void nand_reset(void);

static void wait_idle(void);

static void nand_select_chip(void);

static void nand_deselect_chip(void);

static void write_cmd(int cmd);

static void write_addr(unsigned int addr);

static unsigned char read_data(void);

/* S3C2410的NAND Flash处理函数 */

static void s3c2410_nand_reset(void);

static void s3c2410_wait_idle(void);

static void s3c2410_nand_select_chip(void);

static void s3c2410_nand_deselect_chip(void);

static void s3c2410_write_cmd(int cmd);

static void s3c2410_write_addr(unsigned int addr);

static unsigned char s3c2410_read_data();

/* S3C2440的NAND Flash处理函数 */

static void s3c2440_nand_reset(void);

static void s3c2440_wait_idle(void);

static void s3c2440_nand_select_chip(void);

static void s3c2440_nand_deselect_chip(void);

static void s3c2440_write_cmd(int cmd);

static void s3c2440_write_addr(unsigned int addr);

static unsigned char s3c2440_read_data(void);

/*初始化NAND Flash */

void nand_init(void)

{

#define TACLS 0

#define TWRPH0 3

#define TWRPH1 0

/*判断是S3C2410还是S3C2440 */

if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

{

nand_chip.nand_reset = s3c2410_nand_reset;

nand_chip.wait_idle = s3c2410_wait_idle;

nand_chip.nand_select_chip = s3c2410_nand_select_chip;

nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;

nand_chip.write_cmd = s3c2410_write_cmd;

nand_chip.write_addr = s3c2410_write_addr;

nand_chip.read_data = s3c2410_read_data;

/*使能NAND Flash控制器,初始化ECC,禁止片选,设置时序 */

s3c2410nand->NFCONF = (1<

}

else

{

nand_chip.nand_reset = s3c2440_nand_reset;

nand_chip.wait_idle = s3c2440_wait_idle;

nand_chip.nand_select_chip = s3c2440_nand_select_chip;

nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;

nand_chip.write_cmd = s3c2440_write_cmd;

#ifdef LARGER_NAND_PAGE

nand_chip.write_addr = s3c2440_write_addr_lp;

#else

nand_chip.write_addr = s3c2440_write_addr;

#endif

nand_chip.read_data = s3c2440_read_data;

/*设置时序 */

s3c2440nand->NFCONF = (TACLS<

/*使能NAND Flash控制器,初始化ECC,禁止片选 */

s3c2440nand->NFCONT = (1<

}

/*复位NAND Flash */

nand_reset();

}

这段代码是用于操作Nand Flash的一段源代码。首先我们看到开始定义了一个结构体,里面放置的全是函数指针。他们等待被赋值。然后是定义了一个这种结构体的变量nand_chip。然后是即将操作的函数声明。这些函数将会被其他文件的函数调用。因为在这些函数里一般都只有一条语句,就是调用结构体的函数指针。接着往下看,是针对两种架构的函数声明。然后在nand_init函数中对nand_chip进行赋值,这也就是我们刚刚讲过的,将函数的入口地址赋值给指针。

现在nand_chip已经被赋值了。如果我们要对Nand进行读写操作,我们只需调用nand_chip.read_data()或者nand_chip.write_cmd()等等函数。这是比较方便的地方,另外,这个代码的移植性很强,如果我们又用到了一种芯片,我们就不需要改变整篇代码,只需在nand_init函数中增加对新的芯片的判断,然后给nand_chip赋值即可。所以我说函数指针会使代码具有可移植性,易修改性。

2.C语言操作寄存器

在嵌入式开发中,经常要使用寄存器,对寄存器进行写入,读出等等操作。每个寄存器都有自己固有的地址,通过C语言访问这些地址是一个很重要的环节。

#define GSTATUS1 (*(volatile unsigned int *)0x560000B0)

在这里,我们举一个例子。这是一个状态寄存器的宏定义。首先,通过unsigned int我们能够知道,该寄存器是32位的。因为要防止程序执行过程中直接从cache中读取数据,所以用volatile进行修饰。每次都要重新读取该地址上的值。首先(volatile unsigned int*)是一个指针,我们就假设它为p吧。它存储的地址就是后面的0x560000B0,然后取这个地址的值,也就是*p,所以源代码变成了(*(volatile unsigned int *)0x560000B0),接下来我们就能直接赋值给GSTATUS1来改变地址0x560000B0上存储的值了。

/* NAND FLASH (see S3C2410 manual chapter 6) */

typedef struct {

S3C24X0_REG32 NFCONF;

S3C24X0_REG32 NFCMD;

S3C24X0_REG32 NFADDR;

S3C24X0_REG32 NFDATA;

S3C24X0_REG32 NFSTAT;

S3C24X0_REG32 NFECC;

} S3C2410_NAND;

static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;

有的时候,我们会看到类似这样一种情况的赋值。其实这和我们前面说的差不多。只不过这里是在定义了指针的同时对指针进行赋值。这里首先定义了结构体S3C2410_NAND,里面全部是32位的变量。又定义了这种结构体类型的指针,且指向0x4e000000这个地址,也就是此刻s3c2410nand指向了一个实际存在的物理地址。s3c2410nand指针访问了NFSTAT变量,但我们要的是它的地址,而不是它地址上的值。所以用&取NFSTAT地址,这样再强制转换为unsigned char型的指针,赋给p,就可以直接通过p来给NFSTAT赋值了。

本期先分享到这里,想要进群学习单片机编程的同学可以私信我,回复“我要入门”,与我们一起成长,喜欢的可以点个赞关注我们!

相关问答

为什么nfs一直挂载失败-ZOL问答

在UNIX类操作系统上定义的网络服务有两层级别的权限设置,一是文件系统级别的权限设置,另一个是网络服务自定义的权限设置。参见有用(0)回复1830676226开发...

如何以NFS方式挂载根文件系统

[回答]用NFS方式挂载根文件系统由于原来的内核是用ATBOOT的方式下载的,不知道怎么传递参数(好像不能,网上查的nfs方式都是用U-boot的方式挂载的),因此决...

 仙童公司  物语系列 2nd season 
王经理: 180-0000-0000(微信同号)
10086@qq.com
北京海淀区西三旗街道国际大厦08A座
©2024  上海羊羽卓进出口贸易有限公司  版权所有.All Rights Reserved.  |  程序由Z-BlogPHP强力驱动
网站首页
电话咨询
微信号

QQ

在线咨询真诚为您提供专业解答服务

热线

188-0000-0000
专属服务热线

微信

二维码扫一扫微信交流
顶部