Linkit 系列博文:
联发科Linkit 7688 (一) 上手及在Mac下搭建OpenWrt交叉编译环境,C语言编译Hello,World
联发科Linkit 7688 (二)GPIO基本操作与C语言编程
联发科Linkit 7688 DUO(三): 通过 Arduino 控制外设和传感器
Linkit 7688 DUO(四): 接上各种Arduino传感器和模块——基础篇
Linkit 7688 DUO(五) 接上各种Arduino传感器和模块—扩展篇
Linkit 7688 DUO(六) 加入MQTT物联网协议
前一篇讲了 Linkit 7688DUO开发板接上一些典型Arduino传感器的作法。
本篇,我们要为开发板接上更多的Arduino的传感器和模块了。
一、 前篇概要:
Linkit 7688 DUO开发板上有两个处理器芯片。
一片是 Linkit 7688, 主处理器
一片是 ATmega32U4, 这是Arduino的处理芯片,提供Arduino编程接口,用于控制传感器外设等
两个处理器通过内部串口相连。
Linkit 7688 DUO开发板上, 从ATmega32U4管脚接出的众多管脚,其中:D0-D13 为数字IO口, A0-A5为模拟IO口, S0-S3为串口设备SPI管脚
前篇,我们练习了在开发板上接入LED、开关、继电器、蜂鸣器等, 并制定了一个两个处理器串口通讯的消息协议。
在开发中, 要写两个程序:
1, 写一个Arduino程序, 写入ATmega32U4中。Arduino程序通过串口接收主处理器Linkit 7688送来的消息, 执行相应动作。
2, 写一个主程序,写入Linkit7688中。 主程序通过串口向 ATmega32U4 发送消息
二、温度湿度传感器 (Temperature & Humidity Sensor), 见下图
编一个Arduino程序如下:采用消息协议,当收到消息,则测量温度、湿度,并发送结果消息到主控板。
注意:程序要用到 dht库(请确保已装好)。
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#include <dht.h> #define COMMAND_TEMPERATURE 't' #define ACK_TEMPERATURE 'u' dht DHT; // dht object int pinDHT = 3; //pin connects to DHT Temperature/Humidity sensor void setup() { MessageInit(57600); //init message pinMode(pinDHT, INPUT); //set pinDHT INPUT } void getTemperature() { //Serial.println("in"); int ret = DHT.read11(pinDHT); switch (ret) { case 0: // ok { unsigned char buf[3]; buf[0] = (int)DHT.temperature; //integer part of temperature buf[1] = (int)((DHT.temperature - (int)DHT.temperature)*10); //one digit frac buf[2] = (int)DHT.humidity; //integer part of humidity MessageSend( ACK_TEMPERATURE, buf, 3 ); //send ACK_TEMPERATURE message back return; } case -1: break; //checksum error case -2: break; //Time out error default: break; //unknown error } MessageNAK( COMMAND_TEMPERATURE ); //send NAK message back } void loop() { if ( MessageReceive() ) { if ( MessageCommand() == COMMAND_TEMPERATURE ) { getTemperature(); } } }
Arduino程序等待 COMMAND_TEMPERATURE消息, 调用getTemperature()函数 ,该函数中调用 DHT.read11()读取传感器数据。如果读取数据成功,返回 ACK_TEMPERATURE消息,消息内容三个字节,第一个字节是温度的整数位、第二个字节是温度的小数第1位。第三字节是湿度.
编一个C语言主程序 temperature_test.c,采用消息协议,向Arduino发送COMMAND_TEMPERATURE消息送到,等待Arduino返回 ACK_TEMPERATURE消息, 读取其中的温度和湿度值打印出来。
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h> #include <unistd.h> #include <memory.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_TEMPERATURE 't' #define ACK_TEMPERATURE 'u' //wait ACK_TEMPERATURE message from Arduino int wait_ack_message(message_t * msg) { int times, ret; times = 0; while ( (ret = message_receive(msg)) != 1 && times++ < 30) { usleep(30*1000); } if ( ret == 1 ) { if ( message_command(msg) == ACK_TEMPERATURE ) { char temperature = (char)message_data(msg, 0); printf("Temperature: %d.%d, Humidity:%d\n", temperature, message_data(msg, 1), message_data(msg, 2)); fflush(stdout); return 1; } } return 0; } int main(int argc, char **argv) { int fd; //file descriptor of serial port message_t msg; //message object fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate message_send( &msg, COMMAND_TEMPERATURE, NULL, 0); //send COMMAND_TEMPERATURE wait_ack_message( &msg ); //wait for ACK_TEMPERATURE serial_close(fd); } return 0; }
主程序 发送 COMMAND_TEMPERATURE 消息, 等待 ACK_TEMPERATURE 返回消息, 从返回消息的内容中第一、二字节得到温度值,第三字节得到湿度值。
将C语言程序交叉编译后生成temperature_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 temperature_test
运行结果, 得到了当前温度和湿度:
Temperature: 25.0, Humidity:87
三、倾斜开关、水银开关(TILT SWITCH), 见下图
倾斜开关其实就是一种开关,开关上有一个玻璃管子,管子里有一个水银球。当开关倾斜,水银i球就会滚动。当开关倾斜到一定程度,水银球就会落到管子底部,把管子底部的两根电极接通。如果反向倾斜,则水银球离开管子底部,管子底部的两根电极将不通。因此,也称为水银开关。
倾斜开关可以用于监测货物有否翻倒等。
编一个Arduino程序,采用上例中的通信协议,监控开关状态,如有状态变化,通过串口发送消息到到主控板, 编译上传到ATmegaU32
Arduino程序等待 COMMAND_TEMPERATURE消息, 调用getTemperature() , 其中调用 DHT.read11()读取传感器数据。
如果读取数据成功,返回 ACK_TEMPERATURE消息,消息内容三个字节,第一个字节是温度的整数位、第二个字节是温度的小数第1位。第三字节是湿度。
编一个C语言主程序 temperature_test.c,采用消息协议,向Arduino发送COMMAND_TEMPERATURE消息送到,等待Arduino返回 ACK_TEMPERATURE消息, 读取其中的温度和湿度值打印出来。 交叉编译后生成temperature_test,用scp命令上传到开发板</p><p><pre name="code" class="cpp">#include <stdio.h>
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#define COMMAND_SWITCH 's' int pinSwitch = 3; //pin 3 connects to switch int lastValue = 0; // last value of pin int checkTimes = 0; // check times for key jitter void setup() { MessageInit(57600); //init message < need message_protocol.ino > pinMode(pinSwitch, INPUT); //set pinSwitch INPUT lastValue = digitalRead(pinSwitch); //get last value } void loop() { int value = digitalRead(pinSwitch); //read the switch if (value != lastValue) { //if value changed //eliminate key jitter: check 4 times checkTimes = 0; delay(100); //delay 100 ms while ( value == digitalRead(pinSwitch) && checkTimes++ < 4 ) checkTimes++; //if continous 4 times if (checkTimes >= 4 ) { unsigned char c = value & 0xFF; //change to unsigned char MessageSend( COMMAND_SWITCH, &c, 1); //send message lastValue = value; } } delay(10); //delay in between reads for stability }
编一个C语言主程序 tilt_test.c,采用消息协议,监听串口有否按键消息送到,打印出来, 交叉编译后生成tilt_test,用scp命令上传到开发板
#include <stdio.h> #include <unistd.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_SWITCH 's' int test_switch() { int fd; //file descriptor of serial port message_t msg; //message object fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate //loop while ( 1 ) { if ( 1 == message_receive(&msg) ) { //if received message if ( message_command(&msg) == COMMAND_SWITCH ) { printf("switch value = %d\n", message_data(&msg, 0 ) ); //print value fflush(stdout); } } usleep(10*1000); //wait 10 milli-seconds } serial_close(fd); } return 0; }
将C语言程序交叉编译后生成tilt_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 tilt_test
用手反复倾斜开关,观察水银球来回滚动,和屏幕输出结果:switch value = 1
switch value = 0
switch value = 1
水银球接通开关时,switch value = 0. 水银球不接通开关时, switch value = 1
四、激光发射器(Laser Emit), 见下图
编一个Arduino程序,采用消息协议,收到消息后,将D3设置为HIGH 或 LOW, 则激光将发射或关闭。 Arduino程序如下,请编译后上传到ATmegaU32
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#define COMMAND_LASER 'a' int pinLaser = 3; //pin 3 connects to laser emit module void setup() { MessageInit(57600); //init message < need message_protocol.ino > pinMode(pinLaser, OUTPUT); //set pinLaser OUTPUT } void loop() { if ( MessageReceive() ) { //if receive message if ( MessageCommand() == COMMAND_LASER ) { int value = MessageData(0); if (value == 1) digitalWrite(pinLaser, HIGH); else digitalWrite(pinLaser, LOW); MessageACK( COMMAND_LASER ); } } }
编一个C语言主程序 test_laser.c,采用消息协议,向Arduino发消息。
注意:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h> #include <unistd.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_LASER 'a' int test_laser() { int fd; //file descriptor of serial port message_t msg; //message object unsigned char value; fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate value = 1; message_send( &msg, COMMAND_LASER, &value, 1); //send COMMAND_LASER message, value = 1 sleep(5);//wait 5 seconds value = 0; message_send( &msg, COMMAND_LASER, &value, 1); //send COMMAND_LASER message, value = 0 serial_close(fd); } return 0; }
交叉编译后生成laser_test,用scp命令上传到开发板
将C语言程序交叉编译后生成laser_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 laser_test
运行结果: 程序一运行,则发射器发出一串激光,5秒后,激光关闭
五、光敏电阻接收器(Photoresistor), 见下图
编一个Arduino程序,采用消息协议,不断读取D4口的状态值,如有状态变化,通过串口发送COMMAND_SWITCH消息到到主控板。这个程序同时也接收消息,如果有COMMAND_LASER消息,则打开或关闭激光。
程序如下,请编译上传到ATmegaU32
#define COMMAND_LASER 'a' #define COMMAND_SWITCH 's' int pinLaser = 3; //pin 3 connects to laser emit module int pinPhotoResistor = 4; //pin 4 connects to photoresistor module int lastValue = 0; //last value of photoresistor void setup() { MessageInit(57600); //init message < need message_protocol.ino > pinMode(pinLaser, OUTPUT); //set pinLaser OUTPUT pinMode(pinPhotoResistor, INPUT); //set pinPhotoResistor INPUT lastValue = digitalRead( pinPhotoResistor ); } void loop() { int value = digitalRead( pinPhotoResistor ); if ( value != lastValue ) // PhotoResistor status change { unsigned char c = value & 0xFF; //convert to unsigned char MessageSend( COMMAND_SWITCH, &c, 1); //send COMMAND_SWITCH to linkit 7688 lastValue = value; } if ( MessageReceive() ) { //receive message if ( MessageCommand() == COMMAND_LASER ) { //if is COMMAND_LASER int value = MessageData(0); if (value == 1) digitalWrite(pinLaser, HIGH); //turn LASER on else digitalWrite(pinLaser, LOW); //turn LASER off MessageACK( COMMAND_LASER ); return; } } delay(1); }
编一个C语言主程序 resistor_test.c,采用消息协议,首先打开激光,然后监测有否COMMAND_SWITCH消息送达,如有,则打印出来。同时,对通过的物体计数。
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
程序如下:
#include <stdio.h> #include <unistd.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_SWITCH 's' #define COMMAND_LASER 'a' int test_resistor() { int fd; //file descriptor of serial port message_t msg; //message object unsigned char value; int counter = 0; fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate value = 1; message_send( &msg, COMMAND_LASER, &value, 1); //turn LASER on //loop while ( 1 ) { if ( 1 == message_receive(&msg) ) { //if received message if ( message_command(&msg) == COMMAND_SWITCH ) { //if is COMMAND_SWITCH value = message_data(&msg, 0 ); //get value if ( value == 0 ) counter++; //increase counter //print it out printf("switch value = %d, counter = %d\n", value, counter ); fflush(stdout); } } usleep(10*1000); //wait 10 milli-seconds } serial_close(fd); } return 0; }
将C语言程序交叉编译后生成 resistor_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 resistor_test
运行: 程序一运行,则发射器发出一串激光,将激光对准光敏电阻。当激光射在光敏电阻上时,光敏电阻的输出值为0. 当光敏电阻收不到激光时,光敏电阻的输出值将变为1.
试着用物体穿过激光,则 激光会被遮挡一次,光敏电阻的输出值先为0,再变成1,再变成0. 此时计数器加1. 并打印在屏幕上。
如此,则可以计数了,比如:可以用于门闸计算进门的人数;也可用于生产线上,对通过的物体计数。
运行结果:
switch value = 0, counter = 1
switch value = 1, counter = 1
switch value = 0, counter = 2
switch value = 1, counter = 2
switch value = 0, counter = 3
switch value = 1, counter = 3
。。。
六、红外线接收(IR RECEIVER), 见下图
每个人的家中都有N多个红外线遥控器。
红外线遥控的原理: 遥控器发出某个频率红外线(通常是38K), 这束红外线有时高、有时低,即以类似“10101100..."的编码方式发出。接收器收到这束红外线后,必须先解码,得到一组数字。这个数字就是遥控器发出的命令。
但是,红外线的编码是比较复杂且很不标准的。各个厂家有不同的编码标准,典型的厂商编码标准有SONY、SHARP、NEC、SANYO、SAMSUNG、PANASONIC、LG等等。一般的家电遥控器,都是用专用的遥控器专用IC芯片去实现编码和解码的,而且不同厂商的IC芯片还不一样。 所以遥控器很不通用。
在Arduino中,我们可以使用上图这个红外线接收器模块,利用Arduino的计算能力进行解码,而且不需依赖专用IC芯片,就可以支持各种厂商的编解码,使得各种遥控器都能遥控Arduino。
6.3 红外线学习程序
比如:我想用家中的电视机遥控器 遥控Arduino. 那么,首先要写一个红外线学习的Arduino程序,用于读取和记录遥控器的编码,如下:
//------------------------------------------------------------------------------ // Include the IRremote library header #include <IRremote.h> //------------------------------------------------------------------------------ int recvPin = 5; //IR receiver connects to pin 5 IRrecv irrecv(recvPin); //init IRrecv unsigned char ir_type = 0; //IR type unsigned int key_count = 0; //key count unsigned long last_key = 0; // last key value unsigned int repeat_count = 0; //repeat key count //+============================================================================= // print IR type string void printIRType() { switch (ir_type) { case NEC: Serial.print("NEC"); break ; case SONY: Serial.print("SONY"); break ; case RC5: Serial.print("RC5"); break ; case RC6: Serial.print("RC6"); break ; case DISH: Serial.print("DISH"); break ; case SHARP: Serial.print("SHARP"); break ; case JVC: Serial.print("JVC"); break ; case SANYO: Serial.print("SANYO"); break ; case MITSUBISHI: Serial.print("MITSUBISHI"); break ; case SAMSUNG: Serial.print("SAMSUNG"); break ; case LG: Serial.print("LG"); break ; case WHYNTER: Serial.print("WHYNTER"); break ; case AIWA_RC_T501: Serial.print("AIWA"); break ; case PANASONIC: Serial.print("PANASONIC"); break ; case DENON: Serial.print("DENON"); break ; default: Serial.print("UNKNOWN"); break ; } } //+============================================================================= // Configure the Arduino // void setup ( ) { irrecv.enableIRIn(); // Start the IR receiver Serial.begin(57600); // Init Serial Serial.println("please press keys on IR remote controller"); } //+============================================================================= // The repeating section of the code // void loop ( ) { decode_results results; // Somewhere to store the results if (irrecv.decode(&results)) // receive an IR code { //whether results has valid value if ( results.decode_type != UNKNOWN && results.value != 0xFFFFFFFF ) { //whether the same key is pressed if (results.value == last_key ) { repeat_count++; } else { last_key = results.value; repeat_count = 0; } if ( repeat_count == 0 ) { //print informations if ( ir_type == 0 ) { ir_type = results.decode_type; //save IR type //print type Serial.print("unsigned char ir_type = "); Serial.print(ir_type); Serial.print("; // "); printIRType(); Serial.println(""); //print ir codes array statement Serial.println("unsigned long ir_codes[] = { "); } //print IR value Serial.print("\t0x"); Serial.print(results.value, HEX); Serial.print(", //KEY "); Serial.println(key_count++); //increase key count } else if ( repeat_count == 3 ) { //repeat 3 times will end current receive task Serial.println("};"); ir_type = 0; key_count = 0; last_key = 0; repeat_count = 0; } } irrecv.resume(); // Prepare for the next value } delay(10); //wait a while for stability }
程序的用途是:当遥控器逐个按下时,记录下按键值,显示在Arduino的串口监视器窗口中。如果同一按键重复按二次,则忽略。如果同一按键重复按三次,则重新开始记录。
将程序编译上传到ATmega32U4, 运行,将电视机遥控器对着红外接收模块,逐个按下遥控器的各个按钮,最后一个按键重复按三次,运行结果如下:
unsigned char ir_type = 3; // NEC
unsigned long ir_codes[] = {
0x20DF08F7, //KEY 0
0x20DF8877, //KEY 1
0x20DF48B7, //KEY 2
0x20DFC837, //KEY 3
0x20DF28D7, //KEY 4
0x20DFA857, //KEY 5
0x20DF6897, //KEY 6
0x20DFE817, //KEY 7
0x20DF18E7, //KEY 8
0x20DF9867, //KEY 9 (最后一个键,要重复按三次)
};
如此,则得到一段代码, 其中:ir_type是遥控器编码厂商类型,ir_codes[]是一个数组,分别记录了第0 至 n个 按键的值。
6.4 红外线接收程序
编一个Arduino程序,采用消息协议,监控红外线接收状态,则发送COMMAND_IR_RECEIVE消息(内容为键值到主控板,程序如下:
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#include <IRremote.h> #define COMMAND_IR_RECEIVE 'i' int recvPin = 5; //IR receiver connects to pin 5 IRrecv irrecv(recvPin); //init IRrecv //IR key codes unsigned char ir_type = 3; // NEC unsigned long ir_codes[] = { 0x20DF08F7, //KEY 0 0x20DF8877, //KEY 1 0x20DF48B7, //KEY 2 0x20DFC837, //KEY 3 0x20DF28D7, //KEY 4 0x20DFA857, //KEY 5 0x20DF6897, //KEY 6 0x20DFE817, //KEY 7 0x20DF18E7, //KEY 8 0x20DF9867 //KEY 9 }; void setup() { MessageInit( 57600 ); // init message < need message_protocol.ino > irrecv.enableIRIn(); // Start the IR receiver } void loop() { unsigned char i; decode_results results; // Somewhere to store the results if (irrecv.decode(&results)) // receive an IR code { if ( results.decode_type == ir_type && results.value != 0xFFFFFFFF ) { //find value in ir_codes array for (i = 0; i < sizeof(ir_codes); i++) { if (results.value == ir_codes[i]) { MessageSend( COMMAND_IR_RECEIVE, &i, 1); //send message, content is key index } } } irrecv.resume(); // Prepare for the next value } delay(10); // delay in between reads for stability }Arduino程序中的 ir_type, ir_codes 就是从红外线学习程序的运行结果中复制来的, 注意:要把 ir_codes数组最后一个数据后的 逗号删去。
Arduino程序的作用是: 当收到红外线信号,在ir_codes数组中查找按键值。如找到,则向主控板发送一个 COMMAND_IR_RECEIVE消息,消息内容是 按键在数组中的序号
将Arduino程序编译上传到ATmega32U4
/* * ir_test.c * */ #include <stdio.h> #include <unistd.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_IR_RECEIVE 'i' int main() { int fd; //file descriptor of serial port message_t msg; //message object fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate //loop while ( 1 ) { if ( 1 == message_receive(&msg) ) { //if received message if ( message_command(&msg) == COMMAND_IR_RECEIVE ) { printf("IR key index = %d\n", message_data(&msg, 0 ) ); //print key index fflush(stdout); } } usleep(10*1000); //wait 10 milli-seconds } serial_close(fd); } else { printf("open serial fail\n"); } return 0; }
将C语言程序交叉编译后生成 ir_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 ir_test
运行: 程序后,当用遥控器对这开发板按键时,则打印出按键结果, 效果如下:IR key index = 1
IR key index = 2
IR key index = 3
。。。
六、红外线发射(IR EMISSION), 见下图
模块上有一个红外线发射二极管
编一个Arduino程序,采用消息协议,接收COMMAND_IR_SEND消息,根据消息内容中的按键序号,翻译为红外线值,发送红外线。程序如下:
#include <IRremote.h> #define COMMAND_IR_SEND 'r' IRsend irsend; //note: for ATmega32U4, IR send module must connects to pin 13 //IR key codes unsigned char ir_type = 3; // NEC unsigned long ir_codes[] = { 0x20DF08F7, //KEY 0 0x20DF8877, //KEY 1 0x20DF48B7, //KEY 2 0x20DFC837, //KEY 3 0x20DF28D7, //KEY 4 0x20DFA857, //KEY 5 0x20DF6897, //KEY 6 0x20DFE817, //KEY 7 0x20DF18E7, //KEY 8 0x20DF9867 //KEY 9 }; void setup() { MessageInit( 57600 ); // init message < need message_protocol.ino > } int sendIR(unsigned char index) { if (index >= sizeof(ir_codes)) return 0; switch (ir_type) { case NEC: irsend.sendNEC(ir_codes[index], 32); return 1; case SONY: irsend.sendSony(ir_codes[index], 32); return 1; case RC5: irsend.sendRC5(ir_codes[index], 32); return 1; case RC6: irsend.sendRC6(ir_codes[index], 32); return 1; case DISH: irsend.sendDISH(ir_codes[index], 32); return 1; case SHARP: irsend.sendSharp(ir_codes[index], 32); return 1; case JVC: irsend.sendJVC(ir_codes[index], 32, false); return 1; case SANYO: return 0; case MITSUBISHI: return 0; case SAMSUNG: irsend.sendSAMSUNG(ir_codes[index], 32); return 1; case LG: irsend.sendLG(ir_codes[index], 32); return 1; case WHYNTER: irsend.sendWhynter(ir_codes[index], 32); return 1; case AIWA_RC_T501: irsend.sendAiwaRCT501(ir_codes[index]); return 1; case PANASONIC: irsend.sendPanasonic(0, ir_codes[index]); return 1; //?address case DENON: irsend.sendDenon(ir_codes[index], 32); return 1; default: return 0; } return 0; } void loop() { if ( MessageReceive() ) { //if message received if ( MessageCommand() == COMMAND_IR_SEND ) { unsigned char index = MessageData(0); //get index of ir_codes from message data(0) if ( sendIR(index) ) //send IR MessageACK( COMMAND_IR_SEND ); //if send OK, response ACK message else MessageNAK( COMMAND_IR_SEND ); //if send fail, response NAK message } } }
编一个C语言主程序 ir_send.c,采用消息协议,向ATmega32U4发送COMMAND_IR_SEND消息,则可以控制它发送红外线
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h> #include <unistd.h> #include "serial.h" #include "message_protocol.h" #define COMMAND_IR_SEND 'r' int main(int argc, char **argv) { int fd; //file descriptor of serial port message_t msg; //message object unsigned char value; if (argc > 1 ) { value = atoi(argv[1]); } else { printf("Usage: ir_send <key>\n"); return 1; } fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0 if ( fd > 0 ) { message_init( &msg, fd, 57600 ); //init message with fd, set baud rate message_send( &msg, COMMAND_IR_SEND, &value, 1); //send COMMAND_IR_SEND message serial_close(fd); } return 0; }
将C程序交叉编译后生成ir_send,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,将红外发射头对着电视机,运行ir_send:
ir_send 0
则可以看到,电视机接收到红外线信号,作出了反应。
ir_send 1
则可以看到,电视机再次接收到红外线信号,作出了反应。
呵呵, 可以遥控电视机了。