当前位置:文档之家› drupal7.x模块开发教程

drupal7.x模块开发教程

drupal7.x模块开发教程
drupal7.x模块开发教程

在本教程中,我们将会建立一个模块,这个模块将列出最近一周内所有新建立的内容节点,比如日志或者论坛的帖子。本章将讲述如何建立最初的模块文件和目录。

开始之前

如果您需要用PHP来查出您站点上的错误,请访问此链接。它将告诉您如何更改Drupal 的设置,使drupal显示错误信息。

为您的模块命名

建立模块的第一步是为它取一个不太长的名字。这个名字将被用在所有的模块文件名和方法名中。所以这个名字必须以字母开头并只能有小写字母和下划线。比如,我们会用"current_posts"作为一个模块名称。注意:一定要确保根据以上规则来取名,因为它将被用于模块名和方法名的前缀。当您运行drupal“钩子“时(请参看后面的章节),drupal将只能识别拥有与您模块文件名称相同前缀的钩子。

请注意不要使用与您站点所有主题相同的名称,这样会使drupal混淆。

创建一个模块目录和模块文件

假如我们决定用"current_posts“的模块名,我们将会在drupal的根目录的以下路径(sites/all/modules /current_posts)创建一个目录。或者如果您要把自己的自定义模块与其他模块区分开,您也可以选择这个路径(sites/all/modules/custom /current_posts)。然后在sites/all/modules/currents_posts目录创建一个名为current_posts.module的文件。注意drupal 并不识别扩展名为.php的文件。如果您为模块添加了php的扩展名,那将不会被识别。drupal 只识别扩展名为.module的php文件。

在Drupal6中,sites/all /modules/是存放自定义模块的理想目录(sites/all/themes/是存放自定义主题的理想目录),因为这个目录存放这所有只与您的站点相关的模块和主题,在您以后升级您的核心模块时,这些自定义模块和主题不会被改写。或者,如果您有多个子站点共享核心模块,而这个自定义模块只在其中一个站点工作,那么您可以使用这个路径来存放:sites/您的子站点/modules

模块文件的开头起始于php的起始标签“

我们的模块还不能被执行,它还没有被激活。稍后我们将激活这个模块。

编码标准

根据drupal编码标准,我们在模块中省略"?>"。否则我们可能会遇到服务器实时运行错误。(注意,在本教程中,我们的示例代码中包括了“?>",这只是为了使代码显示的更好。请在实际应用中忽略"?>")

所有以{模块名}_{方法名}格式命名的方法,都是钩子,都可以被drupal直接调用。其中{方法名}是预定义的方法名后缀。drupal将会调用这些方法来处理数据。所以取一个简单明了的模块名是十分重要的,drupal会知道去哪查找数据。

下一步,我们将踏入钩子的领域。

所有的Drupal模块都有一个"模块名.info"文件,用来储存该模块的元信息。(其实可以理解成模块的描述文件)

该文件的一般格式为:

name = Module Name

description = A description of what your module does.

core = 7.x

在本示例中,我们用我们自己的模块名"current_posts"来代替上面例子中的"Module Name".

如果没有.info文件,drupal不会将我们的模块添加进模块列表。下面就是修改后的.info文件内容:

name = Current Posts

description = A block module that lists links to recent posts.

core = 7.x

我们把以上内容添加到一个名为current_https://www.doczj.com/doc/7f12618805.html,的文件中,并把该文件保存在模块的根目录sites/all/modules/current_posts下。

注意:如果您复制以上代码并粘贴到.info文件,留意description的内容不要有空行,否则本文件将不会正确的读取。

.Info文件的细节

drupal把所有能够放到.info文件的参数都放到了这个网页,请参看。

检查

我们现在有了.info文件,要想从drupal文件列表里找到我们的模块,我们只需要一个空的.module文件就可以了。只需要在同样的模块目录下建立一个.module文件,并在.module 文件里添加

Drupal模块中的注释语言

在您的模块中添加注释来解释您的模块如何工作,是个很好的习惯。我们需要严格的遵从drupal的注释规则来发布补丁或新模块,因为drupal用Doxygen来从代码的注释语言中生成文档。请查询doxygen和注释规范来获得更多相关信息。接下来的教程对大家是非常有帮助的,即使您也许目前并不需要它。

下面是我们的第一个注释:

/**

* @file

* A block module that displays recent blog and forum posts.

*/

?>

@file告诉您此注释适用与整个文件。注释起始于"/**", 结束于"*/"。按照drupal指南所要求的,drupal模块中所有的方法都将用这个注释格式。

运行我们的第一个钩子

钩子是drupal模块的基本。它们让我们把自己的模块整合到drupal核心模块中去。如果你不知到这些,请参看drupal模块的入门。

我们的第一个模块是hook_help. drupal推荐我们在所有模块中应用这个钩子。hook_help为用户提供此模块的帮助信息。要在drupal中运行钩子,我们要把"hook"替换成我们模块的短名,并在module文件中用同样的名字建立一个方法。所以,要在我们的示例模块中运行

hook_help,我们应该在current_posts.module文件中建立一个叫做current_post_help()的方法:

function current_posts_help($path, $arg) {

}

?>

$path变量提供了相关帮助信息的参数:在durpal或模块的什么地方,我们的用户会需要帮助信息。要想处理这个参数的公认的好方法是用switch语句。这是drupal非常流行的别写模式。我们的模块将采用下面这个简短的钩子示例,我们还可以添加注释语言在里面。

/**

* Implements hook_help.

*

* Displays help and module information.

*

* @param path

* Which path of the site we're using to display help

* @param arg

* Array that holds the current path as returned from arg() function

*/

function current_posts_help($path, $arg) {

switch ($path) {

case "admin/help#current_posts":

return '

'. t("Displays links to nodes created on this date") .'

';

break;

}

}

?>

注意我们不应该有"?>"

drupal核心模块会把“admin/help#模块名"链接到drupal的帮助页面"/admin/help/ 或者?q=admin/help"。我们最终将会添加更多的注释语言,请参看注释语言标准。这个方法不仅允许第三方对它的翻译,更加加强了代码的安全性。请参看Localization API来获得更多的信息。

检查

在工具栏点击"模块", 我们便可以在模块列表找到我们的模块。激活模块并点击保存,刷新本页面,您将看到我们的模块旁边有了一个"help"链接。点击这个链接,我们就能看见current_post_help钩子返回的内容了。或者您可以在工具栏点击帮助链接(https://www.doczj.com/doc/7f12618805.html,/admin/help),您将看见我们的帮助链接被列在帮助列表上。

卸载我们的模块并点击保存。(注意:卸载我们当前未完成的模块是很重要的,我们未完成的模块很容易破坏我们的站点。

声明区块

模块可以被用来做各种事情,比如:创建区块(一段简短的内容,通常出现在页面的左右两边);建立特殊的内容类型(就像您现在正在阅读的内容);查询后台信息等等。您也许听说过block模块--专门被用来创建区块内容(比如菜单),或者node模块--专门用来生成页面的内容(比如日志和论坛)。在我们的例子中,我们所建立的是一种block模块,因为我们创建了一个区块(block)。

drupal7提供了至少8个block钩子可以应用。根据我们例子的需求,我们将用到其中的两个。第一个钩子是hook_block_info()。您可能已经猜到了,这个钩子用来告诉Drupal我们要建立的区块的相关信息。我们将用这个钩子来定义一个能够显示最近新提交的内容的区块。您可以使用任意一个模块提供的block钩子,如此您将需要定义相关模块所需的所有区块,在我们的例子中,我们只需要定义一个区块。

要定义我们自己的区块,我们需要打开current_posts.module文件,并建立一个叫做current_posts_block_info方法,如下

/**

* Implements hook_block_info().

*/

function current_posts_block_info() {

$blocks['current_posts'] = array(

'info' => t('Current posts'), //The name that will appear in the block list.

'cache' => DRUPAL_CACHE_PER_ROLE, //Default

);

return $blocks;

}

?>

注意在我们真正的代码中不应该有"?>"在结尾。

代码中的注释已经把这个钩子解释的很充分了。大家可以访问hook_block_info的API页面或者运行一个hook_block_info钩子来了解更多。

我们将把整个队列返回到drupal中。请注意例子中队列的格式和结构,只是drupal指定的队列结构。队列在PHP中被支持和运行的很流畅,drupal沿用并扩展了队列的用途。

在我们的例子中,唯一一个必须的队列元素是info, 但是hook_block_info还能够把其他的设置具体化。比如在这个里,我们把缓冲存储设置为默认。请参看hook_block_list来获得完整的可用的元素信息。

别忘了返回整个队列到drupal

检查

访问模块页面并激活Current Posts模块,保存设置。下一步,访问Structure(结构)->Blocks (区块)页面。在页面的底部,我们应该能够找到被命名为"Current posts"的区块。如果能够找到,说明我们的钩子安装成功了。下一步我们就可以卸载我们的模块并保存设置了。注意:我们必须卸载未完成的模块,因为未完成的代码可能会导致我们的站点无法工作。

获取信息

下一步我们将建立一个自定义方法来获取最近在站点发布的内容。当一个节点被建立时,Drupal把它的建立时间存储到数据库中。我们将用这个数据库字段来查询我们所需的信息。

我们本可以把这段代码放到我们下一章要讲的钩子中去,但是把这段代码单独放到一个方法里能够是我们的代码更加清晰明了,便于阅读和管理。

我们将称这个方法为current_posts_contents。我们继续遵循将模块短名作为方法名的前缀的规则,跟着我们放一个非drupal钩子名的词在模块短名后面。这个方法起始于如何获得当前时间。下面是代码的第一部分:

/**

* Custom content function.

*

* Set beginning and end dates, retrieve posts from database

* saved in that time period.

*

* @return

* A result set of the targeted posts.

*/

function current_posts_contents(){

//Get today's date.

$today = getdate();

//Calculate the date a week ago.

$start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);

//Get all posts from one week ago to the present.

$end_time = time();

?>

这段代码用来获得当前时间参数(自从新纪元以来到现在的秒数,请参考mktime来了解这里面的含义和格式),然后我们便可以计算出一周前午夜的时间参数。这段代码是PHP语言编写的,您可以访问https://www.doczj.com/doc/7f12618805.html,来获得更多信息。

下一步我们将用drupal的数据库API来获取我们的节点列表。这是我们自定义方法的第二部分。

//Use Database API to retrieve current posts.

$query = db_select('node', 'n')

->fields('n', array('nid', 'title', 'created'))

->condition('status', 1) //Published.

->condition('created', array($start_time, $end_time), 'BETWEEN')

->orderBy('created', 'DESC') //Most recent first.

->execute();

return $query;

}

?>

drupal有自带的非常健全的数据库语言构造器,它运用了特有的面向对象API。我们要注意INSERT,UPDA TE,DELETE语句将使用以上的格式来构造。drupal将把这个对象转换为相应数据库语言。对于SELECT语句,虽然我们并不是必须要使用以上格式,但是使用以上格式会加深我们对drupal数据库构语句造器的理解。我们在drupal中间到很多类似的结构.

1我们用db_select命令来构造一个SQL语句,我们将需要把数据库表名和它的简写作为参数传给这个命令。

2这里的field命令用来告诉SQL我们要从那个表(第一个参数)查询那些字段信息(第二个参数中的队列)。

3condition命令需要三个参数。第一个参数是要查询的字段。第二个参数数我们要查询的值。第三个参数是比较的条件。如果第三个参数是空,那drupal将使用默认条件--等于“=”。

4order命令将根据传进去第一个参数将查询结果排序,第二个参数决定是升序还是降序。

5execute命令用来编译和执行我们所构造的SQL语句,并返回结果(一个对象)。以下是最终的代码:

/**

* Custom content function.

*

* Set beginning and end dates, retrieve posts from database

* saved in that time period.

*

* @return

* A result set of the targeted posts.

*/

function current_posts_contents(){

//Get today's date.

$today = getdate();

//Calculate the date a week ago.

$start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);

//Get all posts from one week ago to the present.

$end_time = time();

//Use Database API to retrieve current posts.

$query = db_select('node', 'n')

->fields('n', array('nid', 'title', 'created'))

->condition('status', 1) //Published.

->condition('created', array($start_time, $end_time), 'BETWEEN')

->orderBy('created', 'DESC') //Most recent first.

->execute();

return $query;

}

?>

请记住在我们的代码中不要包含"?>"

生成区块内容

访问权限检查

这个是代码的第一部分

function current_posts_block_view($delta = '') {

switch($delta){

case 'current_posts':

$block['subject'] = t('Current posts');

if(user_access('access content')){

//Retrieve and process data here.

}

?>

在把信息显示给用户之前,我们要检查当前的用户是否有权限来查看此信息。在这里,我们执行最基本的权限检查“access content“。您也可以用Drupal所提供的其他的权限检查,或者建立您自己的权限。要查看drupal权限列表,请访问people>list(或者https://www.doczj.com/doc/7f12618805.html,/admin/people). 在权限的下拉列表中,您将看到您可以使用的权限的机器名。这个列表将包含您站点的所有权限,包括任何自定义模块的权限。那permission页面的权限名称并不是机器名,所以您不可以把它们用到代码里。

查看可用权限的另一个方法是参看API参考。输入模块名并加上_permission的后缀,比如node_permission。我们将看到node定义的所有权限。要想知道哪一个权限才是我们需要的没那么容易,比如access_content是我们在这里要用的,但是它不是block模块所提供的,而是node模块提供的。

在代码中建立链接

这里是下一步的代码

//Use our custom function to retrieve data.

$result = current_posts_contents();

//Array to contain items for the block to render.

$items = array();

//Iterate over the resultset and format as links.

foreach ($result as $node){

$items[] = array(

'data' => l($node->title, 'node/' . $node->nid),

);

}

?>

首先,我们在我们自定义的方法中,把内容存储到一个叫作$result的变量中,然后用$item 变量来存放要处理的信息。在循环中,我们访问每一个节点,然后根据节点的信息来构建一个链接。

注意,链接是被l()方法所建立的。(小写的L)。第一个参数定义了链接的名字,在这里是节点的名称。第二个参数定义了链接的路径。所有通向节点的路径总会是像"node/#","#"是节点的ID。l()用这个路径来生成真正的链接。把url转化成相对drupal安装目录的URL

主题化我们的信息

drupal的表示层,也被人们熟知为主题层,是一个可以兼容不同主题的系统。每一个主题都可以控制drupal的外观,并且可以控制CSS文件。Drupal主题是一个很大的方面,我们甚至可以用一整本书来讨论它。在这里我们只用到了drupal主题的皮毛。我们将会研究主题是如何分析解读队列的。

这里是current_posts_block_view 方法的最后一部分。

if (empty($items)) { //No content in the last week.

$block['content'] = t('No posts available.');

} else {

//Pass data through theme function.

$block['content'] = theme('item_list', array(

'items' => $items));

}

}

}

return $block;

}

?>

首先,我们要考虑一种可能性,就是我们可能没有任何内容符合要求。我们的区块应该显示是否有上周心法不的内容。

如果$item变量里面有信息,那么我们将用theme()方法。第一个参数是一个theme钩子。在这个方法中,drupal提供了很多不同theme钩子供我们使用。请参看默认theme钩子列表。我们在这里选择了把信息输出成一个无序的列表,那么我们用到了theme_item_list钩子。第二个参数包含了我们要输出的内容。

您在这里也许有些糊涂了。为什么drupal会明白theme_item_list呢?我们不是在使用theme()么?其实在这里theme() 在寻找一个钩子,类似于theme_hookname的格式。如果直接使用这个格式的钩子,那么hookname就充当了theme()的第一个参数。在这里我们用的是_item_list。它定义了我们要输出的默认的格式。

全部的代码

/**

* Implements hook_block_view().

*

* Prepares the contents of the block.

*/

function current_posts_block_view($delta = '') {

switch($delta){

case 'current_posts':

$block['subject'] = t('Current posts');

if(user_access('access content')){

//Use our custom function to retrieve data.

$result = current_posts_contents();

//Array to contain items for the block to render.

$items = array();

//Iterate over the resultset and format as links.

foreach ($result as $node){

$items[] = array(

'data' => l($node->title, 'node/' . $node->nid),

);

}

if (empty($items)) { //No content in the last week.

$block['content'] = t('No posts available.');

}

else {

//Pass data through theme function.

$block['content'] = theme('item_list', array(

'items' => $items));

}

}

}

return $block;

}

?>

请记住在添加这个代码到我们的模块文件中时,不要添加php的起始和结束符号

测试并纠错

激活模块

点击模块链接(Modules), 或者访问https://www.doczj.com/doc/7f12618805.html,/admin/modules, 然后在模块列表中找到other目录。在那里我们应该能够找到'Current posts'模块。选择激活此模块并保存。现在我们应该能看到在模块名的旁边有一个帮助链接。点击这个链接我们就能看到之前我们在模块里写入的帮助信息了。

激活区块

下一步,我们访问结构->区块, 或者https://www.doczj.com/doc/7f12618805.html,/admin/structure/block。下滑到区块列表的底部。在未激活的区块列表中,我们应该能找到区块名为'Current posts'的区块。把它随便设置在Drupal的一个区域中并保存。访问随便一个其他的页面,我们应该能在我们设定的那个区域找到我们的模块了。恭喜,您已经完成了您的第一个模块。

纠错

如果当您激活模块时,您遇到了'白屏'或者PHP 错误,很可能您的module文件代码中有语法错误。请检查您代码中的标点符号是否正确,比如冒号,逗号等。然后检查我们的模块名,方法名,前缀和后缀都拼写的正确。(一般我们都可以在apache的日志中找到"白屏"的PHP 错误。或者您可以选择改变PHP错误的报告等级)

如果您始终无法找到并改正语法错误,那么您将看到“白屏", 因为drupal将持续的试图把我们的模块在每一个页面运行。最简单的修复这个问题的方法是,删除有问题的模块文件夹,或者把文件夹移出drupal的根目录。这样drupal将不会试图运行这个模块,站点将恢复工作。

清除缓冲

如果在您激活了模块之后,您看不到任何变化,很可能是drupal缓冲了很多之前的信息。一般来说,在激活模块时,drupal缓冲不会影响我们。但是在这里我们依然清除缓冲,因为我们尽量把所有纠错方法放到一起,为以后的纠错提供方便和参考。

访问设置configuration->performance,或者https://www.doczj.com/doc/7f12618805.html,/admin/config/development/performance, 我们就可以看见清除缓冲的按钮。

生成模块设置页面的准备工作

现在,我们已经有了一个完全工作的模块。下一步,我们要添加一些复杂的功能在上面。在一个比较复杂的站点,我们也许并不想把所有最近一周所更新的内容链接都显示给用户。所以,我们要建立一个模块的设置页面,来设置到底要显示多少链接给用户。

注册一个URL

我们用hook_menu()来定义一个URL,在这个URL,我们就可以定义我们自己的设置页面了。(原文所说的是用hook_menu()来定义form,这会误导读者。实际上form是在另一个方法定义的。而hook_menu()只是调用那个方法返回的form,并显示到当前的URL page。下面是hook_menu()的代码。它将与下一章的代码一起工作。)

/**

* Implements hook_menu().

*/

function current_posts_menu() {

$items = array();

$items['admin/config/content/current_posts'] = array(

'title' => 'Current posts',

'description' => 'Configuration for Current posts module',

'page callback' => 'drupal_get_form',

'page arguments' => array('current_posts_form'),

'access arguments' => array('access administration pages'),

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

?>

Creating the configuration form

Last updated May 4, 2012. Created by jn2 on March 30, 2011.

Edited by nl11087, wmostrey, idflood. Log in to edit this page.

Main topic described: Form API

Main functions described: variable_get(), system_settings_form()

Next, we will build the current_posts_form() function. We build the form by adding elements to the $form array. In a pattern similar to the menu $items variable, the name of each element is its key in the array, with that key's value being a specially formatted associative array. In this value array, we list the attributes of the element, this time preceding each key with a hash mark (#).

Add the following to your current_posts.module file:

/**

* Page callback: Current posts settings

*

* @see current_posts_menu()

*/

function current_posts_form($form, &$form_state) {

$form['current_posts_max'] = array(

'#type' => 'textfield',

'#title' => t('Maximum number of posts'),

'#default_value' => variable_get('current_posts_max', 3),

'#size' => 2,

'#maxlength' => 2,

'#description' => t('The maximum number of links to display in the block.'),

'#required' => TRUE,

);

return system_settings_form($form);

}

?>

(Remember not to include the opening or closing PHP tags when you add this section.)

The element attributes

Here we create a text field, with a title of 'Maximum number of posts', and a description, which

will appear below the field. Note that both of these strings are passed through the t() function for translation. Size is 2, maximum length is 2. The Form API will automatically validate the maxlength attribute when the form is submitted and throw an error if the length exceeds 2. We have also designated the field as required. The form API will mark it with an asterisk and will throw an error if the form is submitted with no value in the field. See the forms_api_reference for the complete list of available elements and properties.

Persistent variables

Certain data, like system settings and user-configurable information, needs to be saved and retrievable for a website to function properly. Drupal accomplishes this through the use of persistent variables. These variables are stored in a database table with keys provided by the implementing module.

The function variable_get() retrieves a persistent variable, and variable_set(), as you might expect, sets one. We use variable_get() above to retrieve the value of our field if it has been set. If not, we specify a default value of 3. variable_get() uses the name of the element, current_posts_max, to find the relevant data.

System settings

Drupal makes it easy for us to save the form's data with the function system_settings_form(). By using the function in our code, we tell Drupal to provide a submit button and to save data into persistent variables using variable_set(). It will also provide a green confirmation message when data is successfully saved, and a red error message if something went wrong. If you prefer, you can create a submit function yourself, (see Form API Quickstart Guide) but for now, we will use this handy shortcut.

Editing the query

We must add two lines of code to our query function, current_posts_contents, one using variable_get() to retrieve the data from our settings form, and the other adding the range function to include this limit in the query. Here's the revised function, with the new lines noted in comments:

function current_posts_contents() {

//Get today's date.

$today = getdate();

//Calculate midnight a week ago.

$start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);

//Get all posts from one week ago to the present.

$end_time = time();

//NEW LINE

$max_num = variable_get('current_posts_max', 3);

//Use Database API to retrieve current posts.

$query = db_select('node', 'n')

->fields('n', array('nid', 'title', 'created'))

->condition('status', 1) //Published.

->condition('created', array($start_time, $end_time), 'BETWEEN')

->orderBy('created', 'DESC') //Most recent first.

->range(0, $max_num) //NEW LINE

->execute();

return $query;

}

?>

Using variable_get(), we save the configuration setting into the $max_num variable or assign a default of 3. Then we add the range method to our select query. That method's first argument is set to zero to specify starting at the beginning of the set. The second argument, $max_num, determines how many records to return.

Add configuration button in Modules page

In your current_https://www.doczj.com/doc/7f12618805.html, file add the following line to create a linked button to your configuration page in the modules page.

name = Current Posts

description = A block module that lists links to recent posts.

core = 7.x

; NEW LINE

configure = admin/config/content/current_posts

?>

Check

Go ahead and again enable your module. Then you will need to clear the menu cache, so that Drupal will recognize the new URL. (Drupal caches a lot of data, including a list of all the URLs it recognizes.) To clear the cache, go to Configuration > Performance or https://www.doczj.com/doc/7f12618805.html,/admin/config/development/performance, and click the Clear all caches button.

Now you can test the settings form. Navigate to it: Configuration > Content authoring > Current posts or https://www.doczj.com/doc/7f12618805.html,/admin/config/content/current_posts. Adjust the number of links and save the configuration. The maximum number of links in the block should adjust accordingly. See how system_settings_form() has added a submit button and gives you a confirmation message when you have successfully saved.

Please note: be sure to disable your module before continuing.

检查数据

表格的API提供了出色的默认表格数据检查机制,但是夜允许我们建立自己的数据检查方法。在这里,我们需要确保用户输入的数字大于0。检查数据的方法和validate钩子很相似,只是用表格的ID代替了模块名。所以我们的数据核实方法应该叫做current_posts_form_validate($form, &$form_state)。不要把这个与validate钩子想混淆,validate 钩子是系统钩子,而我们的方法是自己建立的某一个表格的数据检查方法。

请注意$form_state队列变量,这个参数在表格方法和数据检查方法中都要用到。$form_state 队列中含有表格在每个状态中所包含的信息和当前状态。用户所输入的数据储存在$_POST 变量中,先要被检查是否符合表格的结构,然后会被传送到表格检查方法和提交方法。队列的“value “关键字默认储存了用户所属入的信息。请参看$form_state()的关键字列表drupal_build_form()。

添加下面的方法到您的current_posts.module模块文件中:

/**

* Implements validation from the Form API.

*

* @param $form

* A structured array containing the elements and properties of the form.

* @param $form_state

* An array that stores information about the form's current state

* during processing.

*/

function current_posts_form_validate($form, &$form_state){

$max_num = $form_state['values']['current_posts_max'];

if (!ctype_digit($max_num)){

form_set_error('current_posts_max', t('Y ou must enter a number for the maximum number of posts to display.'));

}

}

?>

请记住不要包含PHP的开始和结束符号

测试数据

首先,我们从$form_state队列中获取模块设置表格的数据并把他们存在一个变量中。然后我们便可以查看这是否是一个数字。如果不是,我们就用form_set_error来返回一个错误信息。这个方法的第一个参数表明您的表格的field名,是哪一个field出现了错误。第二个参数是您想向用户显示的信息内容。这个信息是用红色的框包围起来的。

如果用户所输入的信息通过了第一个检查,那么我们要检查它是不是一个正数。如果不是,我们还是用form_set_error来显示错误信息。注意错误信息的string是要用t()方法来翻译一下的。

检查

激活您的模块并访问设置页面。输入一些数字来看看我们的数据检查方法是不是工作。如果您要添加一些代码,请确保您的模块是未激活的。

为页面建立自定义的权限

目前为止,我们已经有了一个区块和一个设置表格。区块显示了所能够显示的最多的链接。但是,也许存在更多的链接,我们的区块的大小不够显示。所以我们需要一个页面来显示更多的最近一周所新建的内容。

自定义权限

首先,我们用hook_permission()建立一个定义权限。这个钩子所定义的权限可以在people->Permission页面设置。(https://www.doczj.com/doc/7f12618805.html,/admin/people/permissions)只有那些拥有这个权限的用户才能访问我们将要建立的页面

添加下列代码到我们的模块文件:

/**

* Implements hook_permission().

*/

function current_posts_permission(){

return array(

'access current_posts content' => array(

'title' => t('Access content for the Current posts module'),

)

);

}

?>

这个钩子的定义严格遵循了Drupal队列的模式。重点在于机器可读的钩子名,他应该和我们要建立的hook_menu()名相同。'title'定义了这个权限的名称,它将出现在权限管理页面。这个名称应该被t()方法所翻译。请参看hook_permission()来查询所有可用的选项参数。

注册URL并为页面方法命名

我们将编辑current_posts_menu()钩子,来建立一个路径和新页面的名称。下面是drupal命名的一个快速提示:如果我们要建立的私有的方法,别的模块基本不会用到的,那么我们用下划线来作为方法名的开头,比如_your_module_name_。如果我们的方法是公开的,其他模块会频繁的用到它,我们也不会频繁的更改它的参数,那么我们不用下划线作为名字的开头,比如your_module_name_。如果我们要执行的是一个钩子,那么我们必须遵循your_module_name_hookname的格式。所以,如果我们没有执行一个钩子,我们已定要检查我们的命名没有恰巧符合一个钩子的格式,否则系统将认为这是一个钩子。

页面的callback是一个非常好的私有方法的例子。所以我们的命名起始与一个下划线+模块名+'page'。把下面的代码作为队列的第二个元素添加到我们的current_posts_menu()方法。确保我们return $items是方法的最后一行,记住不要包含php的开始和结束符。

$items['current_posts'] = array(

'title' => 'Current posts',

'page callback' => '_current_posts_page',

'access arguments' => array('access current_posts content'),

'type' => MENU_NORMAL_ITEM, //Will appear in Navigation menu.

);

?>

把这个menu item和前一个menu item做对比。前一个item需要有description作为设置页面的描述。在这里,这是不重要的。因为我们将建立的页面方法不会调用drupal_get_form,我们并没有任何页面参数要传进去。新建的权限将成为我们的access argument。因为我们没有用admin/config路径,所以我们的页面链接将出现在Navigation menu。

检查

激活我们的模块,并检查Navigation menu。我们应该能看到Current posts的链接。如果看不到,请试着清空缓冲,然后再试试。因为我们还没有编写页面方法,所以这个链接将引导我们到一个空白页面,或者错误信息。在继续编写我们的模块前,请记住卸载当前模块。

启用数据库命令

我们要新建的页面方法基本会与current_posts_block_view的功能相同,它将从我们要建立的current_posts_contents方法中获得数据。所以我们需要在current_posts_contents方法中来读取数据库并获得数据。我们所需要做的就是编辑这个方法,调用一些数据库命令,然后把返回的信息传给页面。

下面是我们要编辑的代码:

function current_posts_contents($display){ //$display argument is new.

//Get today's date.

$today = getdate();

//Calculate midnight a week ago.

$start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);

//Get all posts from one week ago to the present.

$end_time = time();

$max_num = variable_get('current_posts_max', 3);

//Use Database API to retrieve current posts.

$query = db_select('node', 'n')

->fields('n', array('nid', 'title', 'created'))

->condition('status', 1) //Published.

->condition('created', array($start_time, $end_time), 'BETWEEN')

->orderBy('created', 'DESC'); //Most recent first. Query paused here.

if ($display == 'block'){

// Restrict the range if called with 'block' argument.

$query->range(0, $max_num);

} //Now proceeds to execute().

//If called by page, query proceeds directly to execute().

return $query->execute();

}

?>

首先,我们把$display这个变量假如到方法中。然后在数据库命令构建结束后,我们来判断这个变量,来决定如何继续构建和运行数据库命令。如果这个变量是'block',表明是block 在请求信息,那么我们则限制选择的范围,因为block能显示的条目有限。如果变量参数是'page'。表明是page页面在请求信息,那么我们将不对数据库选择范围进行限制,页面将显示所有信息。

编辑current_posts_block_view

如果我们要想我们的代码像current_posts_block_view一样工作,必须要在block区块的显示代码中加入雷斯下面的代码来调用我们所建立的方法。

$result = current_posts_contents('block');

?>

要想代码工作得像block_view一样,只需把…block?作为参数传到方法中。

主题化页面

现在我们将要编写一个页面方法,来把页面内容返回到我们之前建立的current_posts_menu()钩子中去。下面是代码的第一部分:

/**

* Custom page callback function, declared in current_posts_menu().

*/

function _current_posts_page() {

$result = current_posts_contents('page');

//Array to contain items for the page to render.

$items = array();

//Iterate over the resultset and format as links.

foreach ($result as $node) {

$items[] = array(

'data' => l($node->title, 'node/' . $node->nid),

);

}

?>

是不是看上去跟之前所编写的代码很相似?我们调用之前建立的方法来读取数据库信息,传入参数'page…,这样程序就会返回所有的信息。然后我们就可以遍历返回的信息,为美一个节点生成链接。

解析队列

下面我们将进入Drupal的主题系统来把我们的队列内容输出成特定的格式。drupal7总是把页面的内容储存在队列里,然后主题系统将才把内容打印输出。这样我们就尽可能长时间的可以把内容当作数据来处理,而不是HTML代码。请参看更完整的解释Render Arrays in Drupal 7下面的代码包含了我们第一个可解析的队列:

if (empty($items)) { //No content in the last week.

$page_array['current_posts_arguments'] = array(

//Title serves as page subtitle

'#title' => t('All posts from the last week'),

'#markup' => t('No posts available.'),

);

return $page_array;

}

?>

这段代码跟current_posts_block_view()方法(当没有信息显示时)的显示效果一样。我们建立一个队列变量$page_array。变量名只要不合其他变量方法名冲突,是无关紧要的。为了编码的一致性,我们沿用模块名为变量名的前缀。

子队列严格的遵循可解析队列的格式。元素名前缀为"#",应用解析队列API中的元素。#title 元素定义了这个队列包含的内容的标题。页面的标题是由curent_posts_menu()定义的,所以这里定义的是子标题。#markup是最简单的元素,在这里提供一个您要显示的string。您也可以用HTML代码。只要用t()方法来翻译他们即可。

您可能发现这个方法看上去与我们之前建立的设置表格的方法相似。他们都用…#?来当作元素的前缀。form API总是用render API的元素,但是我们之前没有很好的把这一部分写到文档里。现在在drupal7,我们能够从form API索引找到所有form API所用到的元素。

主题钩子的建议

下面是代码的最后一部分:

else {

$page_array['current_posts_arguments'] = array(

'#title' => t('All posts from the last week'),

'#items' => $items,

//Theme hook with suggestion.

'#theme' => 'item_list__current_posts',

);

return $page_array;

}

}

?>

我们又用到了#title元素。跟着的两行我们调用theme_item_list()来解析队列。在current_posts_block_view()方法中,我们用到了下面的代码:theme('item_list', array('items' => $items));,它们的功能是一样的。$items变量包含了一个链接的队列,被付给了#items元素,#theme元素定义了我们将用drupal默认的item lists作为主题输出格式。

在这里我们注意到一个细节。我们在主题钩子调用是用了两个下划线加模块名。这样是为了给其他主题编写者更大的自由。如果我们在这里只用默认的主题钩子,其他主题编写者做的任何改动将被应用于这个钩子,不只是我们的列表。在这里,主题将只修改我们的本模块的输出格式。

两个下划线是drupal认识的格式,它表示这是一个建议的主题钩子。如果您需要,您可以编写任意的有双下划线的建议。drupal将优先查找建议的主题钩子,然后才是默认的钩子。本模块并不使用建议的主题钩子,但是这是可以被加入的。

检查

是时候检查我们的模块了。激活我们的模块并点击Navigation目录的链接。如果我们是未登录状态或者没有权限访问,我们将无法看到链接。

Adding a 'More' link

Last updated April 24, 2011. Created by jn2 on April 15, 2011.

Edited by izus. Log in to edit this page.

Main topic described: Block system, Render arrays, Menu system

Main function described: drupal_set_title()

With this last addition to the module, we will pull together what you have learned about the block system, the menu system, and render arrays, and throw in a workaround for a minor bug in the current version of Drupal 7.

It may have occurred to you that access to this page belongs not in the 'Navigation' menu, but through a 'More' link at the bottom of the 'Current posts' block. That was the plan all along, but we started with a menu link to show how it works.

If you looked at the Default theme implementations referenced back in Generating block content, you may have noticed the theme_more_link theme hook. We'll use that, along with a theme hook suggestion, to theme the 'More' link for our block.

Child render elements

We'll start by converting the call to theme_item_list into a render array as we did in the page function. We'll also make it a child of block['content'] to allow for the 'More' link as a sibling. Here's the revised code for the last section of current_posts_block_view:

else {

//Pass data through theme function.

$block['content']['posts'] = array(

'#theme' => 'item_list__current_posts__block',

'#items' => $items,

);

?>

Remember not to include the PHP markers in your code.

We move the item list code to $block['content']['posts'], making it a child element. Y ou can name the child element whatever you like, as long as it doesn't start with a hash mark (#). We convert the call to theme_item_list into a render array, then add the __current_posts theme hook suggestion. This we follow with a second suggestion in case a themer wants to render the lists in the block and page differently.

Here's new code for the 'More' link to add directly after the last listing:

//Add a link to the page for more entries.

$block['content']['more'] = array(

'#theme' => 'more_link__current_posts',

'#url' => 'current_posts',

'#title' => t('See the full list of current posts.'),

);

}

?>

Here we make the 'More' link a sibling to the posts array and provide the two parameters this theme hook requires, the path and title. The title provides text which will appear as a tooltip when the mouse hovers over the link. We give this theme hook a suggestion as well.

Edit current_posts_menu()

At this point, we have links to the page both in our block and in the 'Navigation' menu. We don't want a link in the menu, so we'll edit current_posts_menu() to take it off. All you need to do is change the type attribute for the page item. Delete MENU_NORMAL_ITEM and replace it with MENU_CALLBACK. This type provides a path and attributes only, with no menu link. Should you have your module enabled, you'll need to disable then re-enable it for this change to take effect.

Page title fix

Enable your module and follow the 'More' link in the block, then note the page title. 'Home'? Not what we had in mind. This is caused by a bug in the first version of Drupal 7. (If you see the 'Current posts' title, you are using a later version that is not in release at the time of this writing.) There is a patch in the works, but we need to code for the current release. Even when the bug is fixed, we can't be certain that our module won't be used on an installation that has not been updated.

The workaround is to use the function drupal_set_title(). Add the following to the beginning of

nRF24L01无线通信模块使用手册12

深圳市德普施科技有限公司 nRF24L01无线通信模块使用手册 一、模块简介 该射频模块集成了NORDIC公司生产的无线射频芯片nRF24L01: 1.支持2.4GHz的全球开放ISM频段,最大发射功率为0dBm 2.2Mbps,传输速率高 3.功耗低,等待模式时电流消耗仅22uA 4.多频点(125个),满足多点通信及跳频通信需求 5.在空旷场地,有效通信距离:25m(外置天线)、10m(PCB天线) 6.工作原理简介: 发射数据时,首先将nRF24L01配置为发射模式,接着把地址TX_ADDR和数据TX_PLD 按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从发送堆栈中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC_CNT)达到上限,MAX_RT置高,TX_PLD不会被清除;MAX_RT或TX_DS置高时,使IRQ变低,以便通知MCU。最后发射成功时,若CE为低,则nRF24L01进入待机模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入待机模式2。 接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。当接收方检测到有效的地址和CRC时,就将数据包存储在接收堆栈中,同时中断标志位RX_DR置高,IRQ变低,以便通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。 三、模块引脚说明

NRF24L01无线模块收发程序例程

//下面是接收的NRF24L01的程序。 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include #include "nrf24l01.h" #include #define uchar unsigned char #define uint unsigned int sbit IRQ =P1^2;//输入 sbit MISO =P1^3; //输入 sbit MOSI =P1^1;//输出 sbit SCLK =P1^4;//输出 sbit CE =P1^5;//输出 sbit CSN =P1^0;//输出 uchar RevTempDate[5];//最后一位用来存放结束标志 uchar code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址 /*****************状态标志*****************************************/ uchar bdata sta; //状态标志 sbit RX_DR=sta^6; sbit TX_DS=sta^5; sbit MAX_RT=sta^4; /*****************SPI时序函数******************************************/ uchar NRFSPI(uchar date) { uchar i; for(i=0;i<8;i++) // 循环8次 { if(date&0x80) MOSI=1; else MOSI=0; // byte最高位输出到MOSI date<<=1; // 低一位移位到最高位 SCLK=1; if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据date|=0x01; // 读MISO到byte最低位 SCLK=0; // SCK置低 } return(date); // 返回读出的一字节 } /**********************NRF24L01初始化函数*******************************/ void NRF24L01Int() {

nRF24L01无线通信模块使用手册

nRF24L01无线通信模块使用手册 一、模块简介 该射频模块集成了NORDIC公司生产的无线射频芯片nRF24L01: 1.支持2.4GHz的全球开放ISM频段,最大发射功率为0dBm 2.2Mbps,传输速率高 3.功耗低,等待模式时电流消耗仅22uA 4.多频点(125个),满足多点通信及跳频通信需求 5.在空旷场地,有效通信距离:25m(外置天线)、10m(PCB天线) 6.工作原理简介: 发射数据时,首先将nRF24L01配置为发射模式,接着把地址TX_ADDR和数据TX_PLD按照时序由SPI 口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD 从发送堆栈中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC_CNT)达到上限,MAX_RT置高,TX_PLD不会被清除;MAX_RT或TX_DS置高时,使IRQ变低,以便通知MCU。最后发射成功时,若CE为低,则nRF24L01进入待机模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入待机模式2。 接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。当接收方检测到有效的地址和CRC时,就将数据包存储在接收堆栈中,同时中断标志位RX_DR置高,IRQ 变低,以便通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。 二、模块电气特性 参数数值单位 供电电压5V 最大发射功率0dBm 最大数据传输率2Mbps 电流消耗(发射模式,0dBm)11.3mA 电流消耗(接收模式,2Mbps)12.3mA 电流消耗(掉电模式)900nA 温度范围-40~+85℃ 三、模块引脚说明 管脚符号功能方向 1GND电源地 2IRQ中断输出O 3MISO SPI输出O 4MOSI SPI输入I 5SCK SPI时钟I 6NC空 7NC空 8CSN芯片片选信号I 9CE工作模式选择I 10+5V电源

NRF24L01无线模块C语言程序

NRF24L01无线模块C语言程序 24MHz晶振 #include #include #include #include #include #include #define U8 unsigned char #define U16 unsigned int #define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节 #define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节 #define TX_DATA_WITDH 1//发送数据宽度1个字节 #define RX_DATA_WITDH 1//接收数据宽度1个字节 #define R_REGISTER 0x00//读取配置寄存器 #define W_REGISTER 0x20//写配置寄存器 #define R_RX_PAYLOAD 0x61//读取RX有效数据 #define W_TX_PAYLOAD 0xa0//写TX有效数据 #define FLUSH_TX 0xe1//清除TXFIFO寄存器 #define FLUSH_RX 0xe2//清除RXFIFO寄存器 #define REUSE_TX_PL 0xe3//重新使用上一包有效数据 #define NOP 0xff//空操作 #define CONFIG 0x00//配置寄存器 #define EN_AA 0x01//使能自动应答 #define EN_RXADDR 0x02//接收通道使能0-5个通道 #define SETUP_AW 0x03//设置数据通道地址宽度3-5 #define SETUP_RETR 0x04//建立自动重发 #define RF_CH 0x05//射频通道设置 #define RF_SETUP 0x06//射频寄存器 #define STATUS 0x07//状态寄存器 #define OBSERVE_TX 0x08//发送检测寄存器 #define CD 0x09//载波 #define RX_ADDR_P0 0x0a//数据通道0接收地址 #define RX_ADDR_P1 0x0b//数据通道1接收地址 #define RX_ADDR_P2 0x0c//数据通道2接收地址 #define RX_ADDR_P3 0x0d//数据通道3接收地址 #define RX_ADDR_P4 0x0e//数据通道4接收地址 #define RX_ADDR_P5 0x0f//数据通道5接收地址

NRF24L01功能使用文档

NRF24L01使用文档 基于c8051f330单片机

目录 芯片简介 (3) 1 NRF24L01功能框图 (4) 2 NRF24L01状态机 (5) 3 Tx与Rx的配置过程 (7) 3.1 Tx 模式初始化过程 (7) 3.2 Rx模式初始化过程 (8) 4控制程序详解 (9) 4.1 函数介绍 (9) 4.1.1 uchar SPI_RW(uchar byte) (9) 4.1.2 uchar SPI_RW_Reg (uchar reg, uchar value) (10) 4.1.3 uchar SPI_Read (uchar reg); (10) 4.1.4 uchar SPI_Read_Buf (uchar reg, uchar *pBuf, uchar bytes); (11) 4.1.5 uchar SPI_Write_Buf (uchar reg, uchar *pBuf, uchar bytes); (11) 4.1.6 void RX_Mode(void) (12) 4.1.7 void TX_Mode(void) (13) 4.2 NRF24L01相关命令的宏定义 (13) 4.3 NRF24L01相关寄存器地址的宏定义 (14) 5 实际通信过程示波器图 (16) 1)发射节点CE与IRQ信号 (17) 2)SCK与IRQ信号(发送成功) (18) 3)SCK与IRQ信号(发送不成功) (19)

芯片简介 NRF24L01是NORDIC公司最近生产的一款无线通信通信芯片,采用FSK调制,内部集成NORDIC自己的Enhanced Short Burst 协议。可以实现点对点或是1对6的无线通信。无线通信速度可以达到2M(bps)。NORDIC公司提供通信模块的GERBER文件,可以直接加工生产。嵌入式工程师或是单片机爱好者只需要为单片机系统预留5个GPIO,1个中断输入引脚,就可以很容易实现无线通信的功能,非常适合用来为MCU系统构建无线通信功能。

nrf24l01(2.4G模块)

NRF24L01(2.4G模块) 一、模块简介 (1)2.4GHz全球开放ISM频段免许可证使用。 (2)最高工作速率2Mbps,高效GFSK调制,抗干扰能力强。 (3)126频道,满足多点通信和跳频通信需要。 (4)内置硬件CRC检错,和点对点通信地址控制。 (5)低功耗,1.9-3.6V工作,待机模式下22uA;掉电模式900nA。 (6)内置2.4GHz天线,体积小巧:15mm×29mm。 (7)模块可软件设置地址,只有收到本机地址时才会输出数据(提供中断提示),可直接接各种单片机使用,软件编程非常方便。 (8)内稳压电路,使用各种电源包括DC/DC开关电源均有很好的通道效果。 (9)2.54mm间距接口,DIP封闭。 (10)工作于Enhanced ShockBurst具有Automatic packet handling,Auto packet transaction handling,具有可选的内置包应答机制,极大地降低丢包率。 (11)与51单片机P0口连接的时候,需要加10K的上拉电阻,与其余口连接不需要。(12)其他系列的单片机,如果是5V的,请参考该系列单片机IO口输出电流大小,如果超过10mA,需要串联电阻分压,否则容易烧毁模块!如果是3.3V的,可以直接和RF24L01模块的IO口线连接。比如AVR系列单片机。如果是5V的一般串接2K的电阻。 二、接口电路 说明: 1)VCC脚接电压范围为:1.9V-3.6V,不能在这个敬意之外,超过3.6V将会烧毁模块。推荐电压3.3左右。 2)除电源VCC和接地端,其余脚都可以直接和普通的5V单片机IO口直接相连,无需转换。当然对3V左右的单片机更加适用了。 3)硬件上面没有SPI的单片机也可以控制本模块,用普通单片机IO口模拟SPI,不需要单片机真正的串口介入,只需要普通的单片机IO口就可以了,当然用串口也可以。 4)如果需要其他封装接口,比如密脚插针,或者其他形式的接口,可联系我们定做。 三、引脚说明

nrf24l01无线模块NRF24L01模块收发c程序

//许多人都在找nrf24l01无线模块的c程序;我以前刚接触无线//时用的就是nrf24l01模块;搜索了许多程序有很多都没法直接用;甚至还怀疑模块是不是被我搞坏了;拿去让别人检测模块又是好的;为避免大家走弯路;我将我的程序发出来供大家参考; 这是nrf24l01无线模块pcb图; 下面有Nrf24l01无线模块的收发c程序;以下程序经本人亲自测试;绝对能用!! 请注意以下几点: 1、24L01模块的电源电压是否为3V-3.6V之间; 2、如果您用的单片机是5V的话,请在IO口与模块接口之间串一个1K电阻; 3、检查模块的GND是否与单片机的GND相连接 4、先用程序进行调试,如果IO口不同,请更改IO口或相关时序; 5、如果是51系列单片机,晶振请选用11.0592M Hz; 模块供电最好用asm1117 5v转3.3v 稳压 测试单片机是stc89c52;at89c52 通用; 收发一体;

一大截不废话了;上程序;此程序是按键控制led;当按下s的时候对应接受的led会闪闪发光;很简单的~如果要实现其他更先进的功能;自己发掘吧~~ 务必将硬件连接正确;否则;它不会工作的~~当然做什么都要严谨~~错一点就差大了~~ 《《收发一体程序》》 #include #include typedef unsigned char uchar; typedef unsigned char uint; //****************************************NRF24L01端口定义

*************************************** sbit M ISO =P1^3; sbit M OSI =P1^4; sbit SCK =P1^2; sbit CE =P1^1; sbit CSN =P3^2; sbit IRQ =P3^3; //************************************按键*************************************************** sbit KEY=P2^0; //***************************************************************************** sbit led=P2^1; //*********************************************NRF24L01*********************** ************** #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 20 // 20 uints TX payload #define RX_PLOAD_WIDTH 20 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址//***************************************NRF24L01寄存器指令******************************************************* #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收FIFO指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 //*************************************SPI(nRF24L01)寄存器地址**************************************************** #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置 #define EN_RXADDR 0x02 // 可用信道设置 #define SETUP_AW 0x03 // 收发地址宽度设置 #define SETUP_RETR 0x04 // 自动重发功能设置 #define RF_CH 0x05 // 工作频率设置 #define RF_SETUP 0x06 // 发射速率、功耗功能设置 #define STATUS 0x07 // 状态寄存器 #define OBSERVE_TX 0x08 // 发送监测功能 #define CD 0x09 // 地址检测 #define RX_ADDR_P0 0x0A // 频道0接收数据地址 #define RX_ADDR_P1 0x0B // 频道1接收数据地址

NRF24L01参考程序(包含多个实例)

(相关人员如觉得本人水平低下,还请见谅) Nrf24L01的使用程序和使用方法和简单操作: 功能: 无线对发程序。两个模块a,b,实现按下一个按键,会在对方的数码管上显示3或4,在本机上显示1,2。 当一个模块,比如a模块。当两个按键按下其中一个,则会在另一个模块b上显示数字3,4(具体根据按下哪个按键)。以上功能描述,B模块按键按下,如同a模块一样的功能,不做系统性描述了。 下面给出程序中几个地方的解释: #define READ_REG 0x00 // 读寄存器指令 #define WRITE_REG 0x20 // 写寄存器指令 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 #define FLUSH_TX 0xE1 // 冲洗发送FIFO指令 #define FLUSH_RX 0xE2 // 冲洗接收FIFO指令 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 #define NOP 0xFF // 保留 类似这种的描述,可以等同于READ_REG =0x00;这个是经过实际程序测试出来的,比如 以下程序: #include #define k 0xfe void main() { P1=k; } 则会出现此类结果:

MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); // shift next bit into MSB.. SCK = 1; // Set SCK high.. uchar |= MISO; // capture current MISO bit SCK = 0; 此处为spi的核心,是spi协议的编程,其中uchar |= MISO; 表示uchar |= MISO | uchar; MOSI = (uchar & 0x80);其中0x80是1000 0000,与上uchar,这种&,是按位与,故可以从uchar提取出一个电平给mosi。 MOSI = (uchar & 0x80); // output 'uchar', MSB to MOSI uchar = (uchar << 1); 这两句组合起来用,就实现了把uchar编程8位2进制数后的每一位都可以发送给mosi;Uchar的只待对象,就是上面的诸如#define FLUSH_TX 0xE1 这样的数,或者是相关的发送数据。 *pBuf这个并不是一个主要的问题,实际这个是涉及指针问题的,带*的跟地址有关系,但是我们其实不需要很关心编译的时候数据被具体存入哪个地址,即使是很重要的数据。 void init_NRF24L01(void) { inerDelay_us(100); CE=0; // chip enable CSN=1; // Spi disable SCK=0; // SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址 SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21 SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致 SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB } 在整个初始化中我们看到: CE=0; // chip enable CSN=1; // Spi disable 这是设置整个的状态。如过状态设置成待机,则引脚可能变为高阻。(以上并非全部引脚)

数字电子技术项目教程课后作业答案

数字电子技术项目教程 项目1答案: 1.1 (1)27 (2)47 (3)26.5 1.2 (1)100101 (2)110001.101 (3)1000.001001 1.3 (1)(127)8(57)8(2) (1566)8(376)16 (3) (26.32)8(16.68)16 1.4 (1)1011110.100101 (2) 1101001100 (3) 10101111011.1111001 1.5 (1)(01000111)8421BCD(2)(10010011.00010100)8421BCD(3)(00010011)8421BCD 1.6 (1)579 1.7 (1) ()() '()() Y A B C D Y A B C D =++ =++ (2) {()} '{()} Y A B C D E G Y A B C D E G =+++ =+++ (3) () '() Y A B C AB C Y AB C ABC =++ =+ 1.8 (1) Y ABC ABC ABC ABC ABC =++++ (2) Y ABC ABC ABC ABC =+++ (3) Y ABCD ABCD ABCD ABCD ABCD =++++ 1.9 (1) Y=A+B+C (2) Y ABC D =+ (3) Y D AB A C BC =+++ 1.10 (1) Y A C AD BC =++ (2) Y CD ABC AD ABC =+++

(3) Y BD ABC =+ (4) Y=D 1.11 只要有一个输入端为低电平,输出就为高电平,如果没有输入,电路输出低电平;多余输入端不能悬空。 1.12 OC 门输出必须外接上拉,三态门有三个状态:高电平,低电平,高阻态。 1.13 1Y ABC = 2Y A B =+ 1.14 C=0时1Y B =;C=1时1Y AB = 2Y AB AB =+ C=1时3Y A =;C=0时3Y A B =+ C=1时4Y AB =;C=0时4Y A B =+ 1.15 TTL 电路驱动CMOS 电路将TTL 电路输出的高电平提高到3.5V 以上;在CMOS 电路输出端与TTL 电路输入端接入CMOS 驱动器。 项目2答案: 2.1 N 2.2 1、0 2.3 保持、翻转 2.4 1n n n Q JQ KQ +=+、1 n Q D += 2.5 2.6

nrf24l01无线模块

基于nRF24L01的无线温度采集系统设计 1引言 温度采集系统所采集的温度通常通过RS485、CAN总线通信方式传输至上位机,但这种方式维护较困难,不利于工业现场生产;而无线通信GPRS技术传输距离长,通信可靠稳定,但设计复杂、成本昂贵。这里采用工业级内置硬件链路层协议的低成本单芯片nRF24L01型无线收发器件实现系统间的无线 通信,完成无线信号的接收、显示及报警功能。 2nRF24L01简介 nRF24L01是一款工业级内置硬件链路层协议的低成本无线收发器。该器件工作于2.4GHz全球开放ISM频段,内置频率合成器、功率放大器、晶体振荡器、调制器等功能模块,并融合增强型ShockBu rst技术,其输出功率和通信频道可通过程序配置。拥有ShockBurst和Enhanced ShockBurst两种数据传输模式。可直接与单片机I/O连接,外接元件数目少。nRF24L01功耗低,以-6dBm的功率发射时,工作电流仅9mA;接收时,工作电流仅12.3mA,多种低功率工作模式(掉电和空闲模式)更利于节能 设计。 3系统硬件设计 系统硬件设计主要由采集发送和接收显示两部分组成。图1为采集发送电路原理图,该电路主要由温度传感器DS18B20、单片机STC12LE5408和nRF24L01组成。 STC12LE5408是增强型8051单片机,速度快,集成度高,电压范围宽(2.2~3.8V),和MCS-5 1系列单片机指令系统完全兼容。其内部还有8KB Flash程序存储器,512字节RAM、2KB EEPRO M、4路PWM以及硬件看门狗(WDT)等资源.性价比高。 DSl8B20是DALLAS公司生产的单总线数字1-Wire温度传感器,可把温度信号直接转换成串行数字信号供单片机处理,采用1-Wire接口。DSl8B20的数据端DQ可通过4.7kΩ的上拉电阻接STC12LE5 408。nRF24L01的CE,CSN,SCK,MOSI,MISO,IRQ引脚则可接STC12LE5408的任意端口,但需在编程时注意,这里接至P1端口。由于nRF24L01具有接收数据功能,所以接收显示电路由单片机ST C12LE5408、nRF24L01和显示电路组成。所采集的数据也通过串口发送至PC机进行处理。

NRF24L01无线发射简易教程

NRF24L01 简易教程

先来看接口电路,使用的IO 口不是唯一的哦,可随意定义接口,当然是在使用IO 口模拟SPI 且IRQ 中断引脚不使用的使用查询方法判断接收状态的情况下了。作为初探我们就是用简单的IO 模拟SPI 的方法了,中断使用查询的方式。那么该教程讲解的接口与单片机的连接如下: 首先您需要了解NRF24L01,请参阅“NRF24L01 芯片中文资料”或者“NRF24L01 芯片英文资料”。 我们的教程是以一个简单的小项目为大家展示NRF24L01 的使用方法与乐趣。我们所写的教程均是以这种方式的呢,让您在学习的时候明白它能做什么,使您学起来不至于枯燥无味。 作为简易的教程,我们只需要知道它是怎么使用的就够了,我们本教程的目的是用NRF24L01 发送数据和接收数据,且接收方会对比发送的数据与接收的数据,若完全相同则控制LED 闪烁一次,并且把接收到的数据通过串口发送到PC 端,通过串口工具查看接收到的数据。 具体的要求如下: 1、具备发送和接收的能力。 2、发送32 个字节的数据,接收方接收到正确数据之后给予提示,通过LED 闪烁灯形 式。 3、把接收到的数据传送到PC 进行查看。 4、发送端每隔大约1.5 秒发送一次数据,永久循环。以上是程序的要求,若您想自行 设计出硬件接口,您也是可以添加一条呢:使用DIY 方 式设计NRF24L01 的接口板,且包含含单片机平台,使用PCB 方式或者万用板方式均可。如果您想让自己学的很扎实,那么推荐您自行做出接口板子呢。当然若您的能力不足,那么我们不推荐自行做板呢,因为这样会增加您学习的难度,反而起到了反效果呢。 我们使用的方式是画PCB 的方式呢,若您自己做了接口板子,那么您可以对比下一呢,O(∩_∩)O! 我们知道NRF24L01 的供电电压是1.9V~3.6V 不能超过这个范围,低了不工作,高了可能烧毁NRF24L01 芯片。我们常用的STC89C52 的单片机的供电电压是5V,我们不能直接给24L01 这个模块供电,我们需要使用AMS1117-3.3V 稳压芯片把5V 转成3.3V 的电压为24L01 模块供电。 为此我们的设计原理图如下:包含单片机最小系统、供电系统、下载程序接口、5V 转3.3V 电路、NRF24L01 模块接口。并且全部引出单片机的IO 口,另外还加了5 个电源输出接口,为扩展使用。还包括了电源指示LED 以及一个IO 口独立控制的LED,这个独立控制的LED用于NRF24L01 接收成功闪烁指示。为了保证系统的稳定性,在设计中添加了两个滤波电容。

NRF24L01无线模块

XL24L01P‐D01模块手册

尊敬的客户: 您好,感谢您选用本公司的无线模块,为了更快更好的使用此产品,请您仔细阅读本使用说明。无线传输距离受空间环境,输出速率,天线等因素影响,本公司标注的距离为基于本公司的测试硬件的开阔地测试距离,仅供参考。深圳市汇睿微通科技开发有限公司为专业无线模块制造厂商,具有多年的无线模块开发设计和制造生产能力,使用中有任何技术问题,请及时联系本公司的技术支持! 一:模块简介 XL24L01P‐D01是采用挪威NORDIC公司的nrf24L01p 2.4G无线收发IC设计的一款高性能2.4G无线收发模块,采用GFSK调制,工作在2400‐2483M的国际通用ISM频段,最高调制速率可达2MBPS。XL24L01P-D01集成了所有与RF协议相关的高速信号处理部分,如:自动重发丢失数据包和自动产生应答信号等,模块的SPI接口可以利用单片机的硬件SPI口连接或用单片机的I/O口进行模拟,内部有FIFO可以与各种高低速微处理器接口,便于使用低成本单片机。 模块大小32*15.2mm,2.54mm间距的双排插针接口,使用内置PCB天线设计,开阔地1MBPS速率下,收发10个字节的数据量测试距离最远约70米左右。 1.1 模块尺寸: 管脚次序 管脚定义 功能描述 1 GND 电源地(方形焊盘) 2 VIN 输入电源(3.0—3.3V) 3 CE 工作模式选择,RX或TX模式选择 4 CSN SPI使能,低有效 5 SCK SPI时钟 6 MOSI SPI输入 7 MISO SPI输出 8 IRQ 中断输出

二:模块功能 2.1 特性 z工作频率 2400‐2483M,共125个工作频道, 符合国际通用ISM法规, z FSK/GSK调制 z支持2M的高速数据传输,减少发射时间,降低平均功耗。 z当工作在应答模式通信时,快速的空中传输及启动时间,极大的降低了平均功耗收 z自动重发功能,自动检查和重发丢失的数据包,重发时间及重发次数可软件控制z自动应答功能,在收到有效数据后,模块自动发送应答信号,无须另行编程 z内置硬件CRC检错和点对多点通信地址控制 z数据包传输错误计数器及载波检测功能可用于跳频设置 z可同时设置六路接收通道地址,可选择性的打开接收通道 z自动存储未收到的应答信号的数据包 2.2 应用范围 无线遥控 机器人控制 家庭自动化 智能玩具 游戏无线控制器 无线传感器 无线语音

NRF24L01的C51单片机讲解

#include #include /*********************************************************************** ****************/ /* NRF24L01 的管脚定义,以及在本程序中的应用,VCC接3.3V电源,可以通过5V用电压转换芯片 /*得到,NC 管脚可以接可以不接,暂时没用途。本程序应用于51或者52单片机,是两个模块进行通讯 /*成功的简单指示,现象是:模块1的 KEY1 对应模块1的LED1 和模块2的LED3 ,模块1的 KEY2 对应模 /*块1的LED2 和模块2的LED4,发过来也对应。 /*********************************************************************** ****************/ typedef unsigned char uchar; typedef unsigned char uint; /************************************NRF24L01端口定义 ***********************************/ =P1^3; sbit MOSI =P1^2; sbit SCK =P1^1; sbit CSN =P1^0; sbit IRQ =P3^2; //数字输入(可屏蔽中断) /************************************按键 ***********************************************/ sbit KEY1=P2^7;//按键S1 sbit KEY2=P2^2;//按键S2 /************************************数码管位选 ******************************************/ sbit led1=P1^0; //LED0 sbit led2=P1^1; //LED1 sbit led3 =P1^2; //LED2 sbit led4 =P1^3; //LED3 sbit led5 =P1^4; //LED4 /*********************************************NRF24L01****************** *****************/ #define TX_ADR_WIDTH 5 // 5 uints TX address width #define RX_ADR_WIDTH 5 // 5 uints RX address width #define TX_PLOAD_WIDTH 20 // 20 uints TX payload #define RX_PLOAD_WIDTH 20 // 20 uints TX payload uint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址 uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址

NRF24L01详细教程..

先来看接口电路,使用的IO 口不是唯一的哦,可随意定义接口,当然是在使用IO 口模拟SPI 且IRQ 中断引脚不使用的使用查询方法判断接收状态的情况下了。作为初探我们就是用简单的IO 模拟SPI 的方法了,中断使用查询的方式。那么该教程讲解的接口与单片机的连接如下: 首先您需要了解NRF24L01,请参阅“NRF24L01 芯片中文资料”或者“NRF24L01 芯片英文资料”。 我们的教程是以一个简单的小项目为大家展示NRF24L01 的使用方法与乐趣。我们所写教程均是以这种方式的呢,让您在学习的时候明白它能做什么,使您学起来不至于枯燥无味。 作为简易的教程,我们只需要知道它是怎么使用的就够了,我们本教程的目的是用NRF24L01 发送数据和接收数据,且接收方会对比发送的数据与接收的数据,若完全相同则控制LED 闪烁一次,并且把接收到的数据通过串口发送到PC 端,通过串口工具查看接收到的数据。 具体的要求如下: 1、具备发送和接收的能力。 2、发送32 个字节的数据,接收方接收到正确数据之后给予提示,通过LED 闪烁灯形 式。 3、把接收到的数据传送到PC 进行查看。 4、发送端每隔大约1.5 秒发送一次数据,永久循环。 以上是程序的要求,若您想自行设计出硬件接口,您也是可以添加一条呢:使用DIY 方式设计NRF24L01 的接口板,且包含含单片机平台,使用PCB 方式或者万用板方式均可。如果您想让自己学的很扎实,那么推荐您自行做出接口板子呢。当然若您的能力不足,那么我们不推荐自行做板呢,因为这样会增加您学习的难度,反而起到了反效果呢。 我们知道NRF24L01 的供电电压是1.9V~3.6V 不能超过这个范围,低了不工作,高了可能烧毁NRF24L01 芯片。我们常用的STC89C52 的单片机的供电电压是5V,我们不能直接给24L01 这个模块供电,我们需要使用AMS1117-3.3V 稳压芯片把5V 转成3.3V 的电压为24L01 模块供电。 为此我们的设计原理图如下:包含单片机最小系统、供电系统、下载程序接口、5V 转3.3V 电路、NRF24L01 模块接口。并且全部引出单片机的IO 口,另外还加了5 个电源输出接口,为扩展使用。还包括了电源指示LED 以及一个IO 口独立控制的LED,这个独立控制的LED用于NRF24L01 接收成功闪烁指示。为了保证系统的稳定性,在设计中添加了两个滤波电容。

2.4G无线传输模块 NRF24L01

NRF24L01无线反射接收模块

1.所需材料 a)单片机最小系统 b)液晶(显示状态作用) c)NRF24L01无线模块 2.基本须知 a)引脚 i. b)NRF24L01状态机(主要有一下几个状态) i.Power Down Mode:掉电模式 ii.Tx Mode:发射模式 iii.Rx Mode:接收模式 iv.Standby-1Mode:待机1模式 v.Standby-2Mode:待机2模式 c)对模块的固件编程的基本思路如下: i.置CSN为低,是能芯片,配置芯片各个参数。配置参数在Power Down状态中完成 ii.如果是Tx模式,填充Tx FIFO iii.配置完成以后,通过CE与CONFIG中的PWR_UP与PRIM_RX参数确定NRF24L01要切换到的状态。 Tx Mode:PWR_UP=1;PRIM_RX=0;CE=1(保持超过10us就可以) Rx Mode:PWR_UP=1;PRIM_RX=1;CE=1 iv.IRQ引脚会在以下三种情况变低: 1.Tx FIFO发完并且收到ACK(使能ACK情况下) 2.RxFIFO收到数据 3.达到最大重发次数 将IRQ接到外部中断输入引脚,通过中断程序进行处理 d)模块通信中的相互识别,是通过定义发送地址和本机地址(如 )地址可以自定义 3.实现思路

a)使用SPI通信与NRF24L01进行相互通信,需要编写基本通信模块的代码(需要用到读 写数据时序图) b)操作NRF24L01模块需要控制其内部的寄存器,因此要在程序中宏定义模块内部需要使 用的寄存器的地址。 c)使用模块之前需要对模块内的相应寄存器进行初始化设置,同理,其他各个模式也有相应 的初始化设置。 d)若接收到数据,IQR引脚会被拉低,此时可以通过SPI通信模块程序读取相应寄存器的 值,读取出所接收到的数据。 e)

NRF24L01模块说明书

NRF24L01高速嵌入式无线数传模块 说 明 书

2008年12月20日 一、产品特性 2.4GHz全球开放ISM频段,最大0dBm发射功率,免许可证使用 支持六路通道的数据接收 低工作电压:1.9~3.6V低电压工作 高速率:2Mbps,由于空中传输时间很短,极大的降低了无线传输中的碰撞现象(软件设置1Mbps或者2Mbps的空中传输速率) 多频点:125频点,满足多点通信和跳频通信需要 超小型:内置2.4GHz天线,体积小巧,15x29mm(包括天线) 低功耗:当工作在应答模式通信时,快速的空中传输及启动时间,极大的降低了电流消耗。 低应用成本:NRF24L01集成了所有与RF协议相关的高速信号处理部分,比如:自动重发丢失数据 包和自动产生应答信号等,NRF24L01的SPI接口可以利用单片机的硬件SPI口连接或用单片机I/O口进行模拟,内部有FIFO可以与各种高低速微处理器接口,便于使用低成本单片机。 便于开发:由于链路层完全集成在模块上,非常便于开发。 自动重发功能,自动检测和重发丢失的数据包,重发时间及重发次数可软件控制

自动存储未收到应答信号的数据包 自动应答功能,在收到有效数据后,模块自动发送应答信号,无须另行编程 载波检测—固定频率检测 内置硬件CRC检错和点对多点通信地址控制 数据包传输错误计数器及载波检测功能可用于跳频设置 可同时设置六路接收通道地址,可有选择性的打开接收通道 标准插针Dip2.54MM间距接口,便于嵌入式应用 二、基本电气特性 三、引脚说明

说明: 1)VCC脚接电压范围为1.9V~3.6V之间,不能在这个区间之外,超 过3.6V将会烧毁模块。推荐电压3.3V左右。 (2)除电源VCC和接地端,其余脚都可以直接和普通的5V单片机IO口 直接相连,无需电平转换。当然对3V左右的单片机更加适用了。 (3)硬件上面没有SPI的单片机也可以控制本模块,用普通单片机IO 口模拟SPI不需要单片机真正的串口介入,只需要普通的单片机IO口 就可以了,当然用串口也可以了(a:与51系列单片机P0口连接时候,需要加10K的上 拉电阻,与其余口连接不需要。 b:其他系列的单片机,如果是5V的,请参考该系列 单片机IO口输出电流大小,如果超过10mA,需要串联 电阻分压,否则容易烧毁模块!如果是3.3V的,可以 直接和RF24l01模块的IO口线连接。比如AVR系列单片机

相关主题
文本预览
相关文档 最新文档