tag 标签: 远程数据采集

相关博文
  • 热度 25
    2015-8-10 17:04
    1353 次阅读|
    0 个评论
    转自: http://www.embed-net.com/thread-230-1-1.html 0 前言 最近在学习MQTT,发现MQTT还是挺好用的,于是花了点时间做了一个简单的应用示例,希望能给需要做这方面的人一些参考。 相关背景知识: http://www.embed-net.com/thread-224-1-1.html 具体功能为: 1,STM32F405为主控芯片,它通过传感器采集环境数据,比如温度,湿度,光照度,大气压强等; 2,主控芯片通过W5500模块将测量的数据通过MQTT协议方式发布到MQTT服务器(服务器域名和IP见固件程序); 3,主控订阅LED灯控制的消息,当接收到对应的控制指令后点亮或者熄灭对应的LED灯; 4,安卓手机端订阅传感器数据的消息,当接收到消息后将传感器数据在界面显示; 5,安卓手机可发送点亮或者熄灭LED灯的指令到服务器,然后服务器会将该指令转发给STM32主控,然后STM32主控解析该指令并执行指令。 1 单片机端实现 MQTT协议是基于TCP的协议,所以我们只需要在单片机端实现TCP客户端代码之后就很容易移植MQTT了,STM32F4+W5500实现TCP客户端的代码我们以前已经实现过,代码下载地址为: http://www.embed-net.com/thread-87-1-1.html 当然,如果你想在代码里面直接使用服务器域名方式进行连接,我们还得在TCP客户端代码里面集成DNS的代码,当然在上面这个连接里面也有相关的代码。 MQTT代码源码下载地址: http://www.eclipse.org/paho/ 在STM32这边我们使用的是C/C++ MQTT Embedded clients代码。 硬件连接如下图所示: 1.1 MQTT的移植 MQTT的移植非常简单,将C/C++ MQTT Embedded clients的代码添加到工程中,然后我们只需要再次封装4个函数即可: int transport_sendPacketBuffer(unsigned char* buf, int buflen); int transport_getdata(unsigned char* buf, int count); int transport_open(void); int transport_close(void); transport_sendPacketBuffer:通过网络以TCP的方式发送数据; transport_getdata:TCP方式从服务器端读取数据,该函数目前属于阻塞函数; transport_open:打开一个网络接口,其实就是和服务器建立一个TCP连接; transport_close:关闭网络接口。 如果已经移植好了socket方式的TCP客户端的程序,那么这几个函数的封装也是非常简单的,程序代码如下所示: /** * @brief  通过TCP方式发送数据到TCP服务器 * @param  buf 数据首地址 * @param  buflen 数据长度 * @retval 小于0表示发送失败 */ int transport_sendPacketBuffer(unsigned char* buf, int buflen) { return send(SOCK_TCPS,buf,buflen); } /** * @brief  阻塞方式接收TCP服务器发送的数据 * @param  buf 数据存储首地址 * @param  count 数据缓冲区长度 * @retval 小于0表示接收数据失败 */ int transport_getdata(unsigned char* buf, int count) { return recv(SOCK_TCPS,buf,count); } /** * @brief  打开一个socket并连接到服务器 * @param  无 * @retval 小于0表示打开失败 */ int transport_open(void) { int32_t ret; //新建一个Socket并绑定本地端口5000 ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0×00); if(ret != SOCK_TCPS){ printf(“%d:Socket Error\r\n”,SOCK_TCPS); while(1); }else{ printf(“%d:Opened\r\n”,SOCK_TCPS); } //连接TCP服务器 ret = connect(SOCK_TCPS,domain_ip,1883);//端口必须为1883 if(ret != SOCK_OK){ printf(“%d:Socket Connect Error\r\n”,SOCK_TCPS); while(1); }else{ printf(“%d:Connected\r\n”,SOCK_TCPS); } return 0; } /** * @brief  关闭socket * @param  无 * @retval 小于0表示关闭失败 */ int transport_close(void) { close(SOCK_TCPS); return 0; } 完成了这几个函数,然后我们就可以根据官方提供的示例代码实现我们自己的代码了,比如我们向代理服务器发送一个消息的代码如下所示: /** * @brief  向代理(服务器)发送一个消息 * @param  pTopic 消息主题 * @param  pMessage 消息内容 * @retval 小于0表示发送失败 */ int mqtt_publish(char *pTopic,char *pMessage) { int32_t len,rc; MQTTPacket_connectData data = MQTTPacket_connectData_initializer; unsigned char buf ; MQTTString topicString = MQTTString_initializer; int msglen = strlen(pMessage); int buflen = sizeof(buf); data.clientID.cstring = “me”; data.keepAliveInterval = 5; data.cleansession = 1; len = MQTTSerialize_connect(buf, buflen, data); /* 1 */ topicString.cstring = pTopic; len += MQTTSerialize_publish(buf + len, buflen – len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */ len += MQTTSerialize_disconnect(buf + len, buflen – len); /* 3 */ transport_open(); rc = transport_sendPacketBuffer(buf,len); transport_close(); if (rc == len) printf(“Successfully published\n\r”); else printf(“Publish failed\n\r”); return 0; } 下面我们看下主函数的代码,思路也比较清晰: int main(void) { static char meassage ; int rc; char *led; char led_value; float temperature,humidity,light,pressure; srand(0); //配置LED灯引脚 LED_Config(); //初始化配置网络 network_init(); while(1){ memset(meassage,0,sizeof(meassage)); //订阅消息 rc = mqtt_subscrib(“pyboard_led”,meassage); printf(“rc = %d\n\r”,rc); if(rc = 0){ printf(“meassage = %s\n\r”,meassage); //解析JSON格式字符串并点亮相应的LED灯 cJSON *root = cJSON_Parse(meassage); if(root != NULL){ led = cJSON_GetObjectItem(root,”led”)-valuestring; printf(“led = %s\n\r”,led); led_value = cJSON_GetObjectItem(root,”value”)-valueint; if(!strcmp(led,”red”)){ if(led_value){ LED_On(LED_RED); }else{ LED_Off(LED_RED); } }else if(!strcmp(led,”green”)){ if(led_value){ LED_On(LED_GREEN); }else{ LED_Off(LED_GREEN); } }else if(!strcmp(led,”blue”)){ if(led_value){ LED_On(LED_BLUE); }else{ LED_Off(LED_BLUE); } }else if(!strcmp(led,”yellow”)){ if(led_value){ LED_On(LED_YELLOW); printf(“Yellow On\n\r”); }else{ LED_Off(LED_YELLOW); printf(“Yellow Off\n\r”); } } // 释放内存空间 cJSON_Delete(root); }else{ printf(“Error before: \n\r”,cJSON_GetErrorPtr()); } } delay_ms(500); //获取传感器测量数据,该示例使用随机数 temperature = rand()%50; humidity = rand()%100; light = rand()%1000; pressure = rand()%1000; //将数据合成为JSON格式数据 sprintf(meassage,”{\”temperature\”:%.1f,\”humidity\”:%.1f,\”light\”:%.1f,\”pressure\”:%.1f}”,temperature,humidity,light,pressure); //将数据发送出去 mqtt_publish(“pyboard_value”,meassage); } } 完整工程代码可在后面的附件下载。 2 手机端代码实现 手机端我们也使用官方提供的Java库Java client and utilities,下载地址: http://www.eclipse.org/paho/ 将jar文件添加到工程中即可,程序界面如下所示: 上面4个条目分别显示STM32单片机通过W5500发送到服务器端的传感器测量数据; 下面4个图片分别控制板子上的4个LED灯; 消息发送我们采用线程的方式发送,接收采用回调函数方式接收消息。 2.1 实现消息发送 发送消息的代码如下所示: /** * send message */ class PublishThread extends Thread { String topic; MqttMessage message; int qos = 0; MemoryPersistence persistence = new MemoryPersistence(); PublishThread(String topic,String message){ this.topic = topic; this.message = new MqttMessage(message.getBytes()); } public void sendMessage(String topic,String message){ this.topic = topic; this.message = new MqttMessage(message.getBytes()); run(); } @Override public void run() { try { MqttClient sampleClient = new MqttClient(broker, clientId, persistence); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true); connOpts.setKeepAliveInterval(1); System.out.println(“Connecting to broker: ” + broker); sampleClient.connect(connOpts); System.out.println(“Connected”); System.out.println(“Publishing message: ” + message.toString()); message.setQos(qos); sampleClient.publish(topic, message); System.out.println(“Message published”); sampleClient.disconnect(); System.out.println(“Disconnected”); }catch(MqttException me) { System.out.println(“reason “+me.getReasonCode()); System.out.println(“msg “+me.getMessage()); System.out.println(“loc “+me.getLocalizedMessage()); System.out.println(“cause “+me.getCause()); System.out.println(“excep “+me); me.printStackTrace(); } } } 2.2 实现消息接收 接收消息的代码如下所示: 继续阅读:http://www.iwiznet.cn/blog/?p=7409
  • 热度 24
    2015-8-10 17:03
    1434 次阅读|
    0 个评论
    转自: http://www.embed-net.com/thread-230-1-1.html 0 前言 最近在学习MQTT,发现MQTT还是挺好用的,于是花了点时间做了一个简单的应用示例,希望能给需要做这方面的人一些参考。 相关背景知识: http://www.embed-net.com/thread-224-1-1.html 具体功能为: 1,STM32F405为主控芯片,它通过传感器采集环境数据,比如温度,湿度,光照度,大气压强等; 2,主控芯片通过W5500模块将测量的数据通过MQTT协议方式发布到MQTT服务器(服务器域名和IP见固件程序); 3,主控订阅LED灯控制的消息,当接收到对应的控制指令后点亮或者熄灭对应的LED灯; 4,安卓手机端订阅传感器数据的消息,当接收到消息后将传感器数据在界面显示; 5,安卓手机可发送点亮或者熄灭LED灯的指令到服务器,然后服务器会将该指令转发给STM32主控,然后STM32主控解析该指令并执行指令。 1 单片机端实现 MQTT协议是基于TCP的协议,所以我们只需要在单片机端实现TCP客户端代码之后就很容易移植MQTT了,STM32F4+W5500实现TCP客户端的代码我们以前已经实现过,代码下载地址为: http://www.embed-net.com/thread-87-1-1.html 当然,如果你想在代码里面直接使用服务器域名方式进行连接,我们还得在TCP客户端代码里面集成DNS的代码,当然在上面这个连接里面也有相关的代码。 MQTT代码源码下载地址: http://www.eclipse.org/paho/ 在STM32这边我们使用的是C/C++ MQTT Embedded clients代码。 硬件连接如下图所示: 1.1 MQTT的移植 MQTT的移植非常简单,将C/C++ MQTT Embedded clients的代码添加到工程中,然后我们只需要再次封装4个函数即可: int transport_sendPacketBuffer(unsigned char* buf, int buflen); int transport_getdata(unsigned char* buf, int count); int transport_open(void); int transport_close(void); transport_sendPacketBuffer:通过网络以TCP的方式发送数据; transport_getdata:TCP方式从服务器端读取数据,该函数目前属于阻塞函数; transport_open:打开一个网络接口,其实就是和服务器建立一个TCP连接; transport_close:关闭网络接口。 如果已经移植好了socket方式的TCP客户端的程序,那么这几个函数的封装也是非常简单的,程序代码如下所示: /** * @brief  通过TCP方式发送数据到TCP服务器 * @param  buf 数据首地址 * @param  buflen 数据长度 * @retval 小于0表示发送失败 */ int transport_sendPacketBuffer(unsigned char* buf, int buflen) { return send(SOCK_TCPS,buf,buflen); } /** * @brief  阻塞方式接收TCP服务器发送的数据 * @param  buf 数据存储首地址 * @param  count 数据缓冲区长度 * @retval 小于0表示接收数据失败 */ int transport_getdata(unsigned char* buf, int count) { return recv(SOCK_TCPS,buf,count); } /** * @brief  打开一个socket并连接到服务器 * @param  无 * @retval 小于0表示打开失败 */ int transport_open(void) { int32_t ret; //新建一个Socket并绑定本地端口5000 ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0×00); if(ret != SOCK_TCPS){ printf(“%d:Socket Error\r\n”,SOCK_TCPS); while(1); }else{ printf(“%d:Opened\r\n”,SOCK_TCPS); } //连接TCP服务器 ret = connect(SOCK_TCPS,domain_ip,1883);//端口必须为1883 if(ret != SOCK_OK){ printf(“%d:Socket Connect Error\r\n”,SOCK_TCPS); while(1); }else{ printf(“%d:Connected\r\n”,SOCK_TCPS); } return 0; } /** * @brief  关闭socket * @param  无 * @retval 小于0表示关闭失败 */ int transport_close(void) { close(SOCK_TCPS); return 0; } 完成了这几个函数,然后我们就可以根据官方提供的示例代码实现我们自己的代码了,比如我们向代理服务器发送一个消息的代码如下所示: /** * @brief  向代理(服务器)发送一个消息 * @param  pTopic 消息主题 * @param  pMessage 消息内容 * @retval 小于0表示发送失败 */ int mqtt_publish(char *pTopic,char *pMessage) { int32_t len,rc; MQTTPacket_connectData data = MQTTPacket_connectData_initializer; unsigned char buf ; MQTTString topicString = MQTTString_initializer; int msglen = strlen(pMessage); int buflen = sizeof(buf); data.clientID.cstring = “me”; data.keepAliveInterval = 5; data.cleansession = 1; len = MQTTSerialize_connect(buf, buflen, data); /* 1 */ topicString.cstring = pTopic; len += MQTTSerialize_publish(buf + len, buflen – len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */ len += MQTTSerialize_disconnect(buf + len, buflen – len); /* 3 */ transport_open(); rc = transport_sendPacketBuffer(buf,len); transport_close(); if (rc == len) printf(“Successfully published\n\r”); else printf(“Publish failed\n\r”); return 0; } 下面我们看下主函数的代码,思路也比较清晰: int main(void) { static char meassage ; int rc; char *led; char led_value; float temperature,humidity,light,pressure; srand(0); //配置LED灯引脚 LED_Config(); //初始化配置网络 network_init(); while(1){ memset(meassage,0,sizeof(meassage)); //订阅消息 rc = mqtt_subscrib(“pyboard_led”,meassage); printf(“rc = %d\n\r”,rc); if(rc = 0){ printf(“meassage = %s\n\r”,meassage); //解析JSON格式字符串并点亮相应的LED灯 cJSON *root = cJSON_Parse(meassage); if(root != NULL){ led = cJSON_GetObjectItem(root,”led”)-valuestring; printf(“led = %s\n\r”,led); led_value = cJSON_GetObjectItem(root,”value”)-valueint; if(!strcmp(led,”red”)){ if(led_value){ LED_On(LED_RED); }else{ LED_Off(LED_RED); } }else if(!strcmp(led,”green”)){ if(led_value){ LED_On(LED_GREEN); }else{ LED_Off(LED_GREEN); } }else if(!strcmp(led,”blue”)){ if(led_value){ LED_On(LED_BLUE); }else{ LED_Off(LED_BLUE); } }else if(!strcmp(led,”yellow”)){ if(led_value){ LED_On(LED_YELLOW); printf(“Yellow On\n\r”); }else{ LED_Off(LED_YELLOW); printf(“Yellow Off\n\r”); } } // 释放内存空间 cJSON_Delete(root); }else{ printf(“Error before: \n\r”,cJSON_GetErrorPtr()); } } delay_ms(500); //获取传感器测量数据,该示例使用随机数 temperature = rand()%50; humidity = rand()%100; light = rand()%1000; pressure = rand()%1000; //将数据合成为JSON格式数据 sprintf(meassage,”{\”temperature\”:%.1f,\”humidity\”:%.1f,\”light\”:%.1f,\”pressure\”:%.1f}”,temperature,humidity,light,pressure); //将数据发送出去 mqtt_publish(“pyboard_value”,meassage); } } 完整工程代码可在后面的附件下载。 2 手机端代码实现 手机端我们也使用官方提供的Java库Java client and utilities,下载地址: http://www.eclipse.org/paho/ 将jar文件添加到工程中即可,程序界面如下所示: 上面4个条目分别显示STM32单片机通过W5500发送到服务器端的传感器测量数据; 下面4个图片分别控制板子上的4个LED灯; 消息发送我们采用线程的方式发送,接收采用回调函数方式接收消息。 2.1 实现消息发送 发送消息的代码如下所示: /** * send message */ class PublishThread extends Thread { String topic; MqttMessage message; int qos = 0; MemoryPersistence persistence = new MemoryPersistence(); PublishThread(String topic,String message){ this.topic = topic; this.message = new MqttMessage(message.getBytes()); } public void sendMessage(String topic,String message){ this.topic = topic; this.message = new MqttMessage(message.getBytes()); run(); } @Override public void run() { try { MqttClient sampleClient = new MqttClient(broker, clientId, persistence); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true); connOpts.setKeepAliveInterval(1); System.out.println(“Connecting to broker: ” + broker); sampleClient.connect(connOpts); System.out.println(“Connected”); System.out.println(“Publishing message: ” + message.toString()); message.setQos(qos); sampleClient.publish(topic, message); System.out.println(“Message published”); sampleClient.disconnect(); System.out.println(“Disconnected”); }catch(MqttException me) { System.out.println(“reason “+me.getReasonCode()); System.out.println(“msg “+me.getMessage()); System.out.println(“loc “+me.getLocalizedMessage()); System.out.println(“cause “+me.getCause()); System.out.println(“excep “+me); me.printStackTrace(); } } } 2.2 实现消息接收 接收消息的代码如下所示: /** * receive message */ class SubscribeThread extends Thread{ final String topic; MemoryPersistence persistence = new MemoryPersistence(); SubscribeThread(String topic){ this.topic = topic; } @Override public void run(){ try { final MqttClient sampleClient = new MqttClient(broker, clientId, persistence); final MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true); System.out.println(“Connecting to broker: ” + broker); connOpts.setKeepAliveInterval(5); sampleClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable throwable) { System.out.println(“connectionLost”); try { sampleClient.connect(connOpts); sampleClient.subscribe(topic); }catch (MqttException e){ e.printStackTrace(); } } @Override public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { System.out.println(“messageArrived:”+mqttMessage.toString()); System.out.println(topic); System.out.println(mqttMessage.toString()); try { JSONTokener jsonParser = new JSONTokener(mqttMessage.toString()); JSONObject person = (JSONObject) jsonParser.nextValue(); temperature = person.getDouble(“temperature”); humidity = person.getDouble(“humidity”); light = person.getDouble(“light”); pressure = person.getDouble(“pressure”); System.out.println(“temperature = ” + temperature); System.out.println(“humidity = ” + humidity); runOnUiThread(new Runnable() { @Override public void run() { temperatureTextView.setText(String.format(“%.1f”, temperature)); humidityTextView.setText(String.format(“%.1f”, humidity)); lightTextView.setText(String.format(“%.1f”, light)); pressureTextView.setText(String.format(“%.1f”, pressure)); } }); } catch (JSONException ex) { ex.printStackTrace(); } } @Override public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { System.out.println(“deliveryComplete”); } }); sampleClient.connect(connOpts); sampleClient.subscribe(topic); } catch(MqttException me) { System.out.println(“reason “+me.getReasonCode()); System.out.println(“msg “+me.getMessage()); System.out.println(“loc “+me.getLocalizedMessage()); System.out.println(“cause “+me.getCause()); System.out.println(“excep “+me); me.printStackTrace(); } } } 3 实测效果 1,单片机端定时更新传感器数据,手机端也会同步更新; 2,手机端点击4个LED控制的按钮,板子上也会点亮或者熄灭对应的LED; 4 源码下载 4.1 STM32端源码下载   MQTT_STM32_W5500.rar 4.2 手机端源码下载   MQTT_Android.rar 4.3 手机端apk下载   stm32_w5500_mqtt_app.rar
  • 热度 28
    2013-6-26 01:03
    1475 次阅读|
    0 个评论
    工业生产过程中常常需要对温度、湿度、压力、流量等各种工艺参数随时进行检测和监控,同时还要将检测到的数据及时传递给上位机,以实现对参数的随机查询, 对信息的存储与处理,及时调整控制方案,提高生产效率和产品质量。为此,笔者以89C51单片机作为主控制器设计了一种简单易行的远程数据采集系统。 1 系统硬件电路的设计   远程数据采集系统框图,由两部分组成:一是基于89C51实现的现场数据采集电路,二是PC机与89C51之间的远程通讯电路。 1.1 89C51数据采集系统 数据采集系统的硬件原理如图1所示。   该系统选用89C51单片机作为主控制器,此芯片与8051完全兼容,且内部带有4 KB闪速可编程、可擦除PEROM,工作时钟可高达24 MHz。    MAX691主要用来实现掉电保护,同时起到“看门狗”的作用。系统电源突然断电时,MAX691PF0端及时向89C51INT0申请中断,保护采集 的数据不丢失。若软件执行中出现故障,89C51P3.2经一定时间间隔没有脉冲输出时,MAX691将起“看门狗”的作用,使RST复位有效,重新启动系统。   数据存储器6116主要作为数据传输的缓冲,显示电路由8155完成,PA口作键盘输入,PB口作字形显示,PC口作控制线用。8155内部256 BRAM用于存放8通道采集到的原始数据。    数据采集与转换由12位A/D转换器ICL7109来完成。7109是高精度、低噪声、低漂移的双积分模数转换器,其内部带14位锁存器和14位三态输出 寄存器,具有较强的接口处理能力。设定7109为直接接口方式。这种工作方式下,7109可连续进行数据的转换,转换结束时由STATUS发出转换结束信 号送至单片机INT0请求中断。89C51将转换后的数据分两次先低8位后高4位读取。为了实现对8个通道的参数测量,同时尽量降低成本,简化系统配置, 设计了利用模拟多路开关CD4051进行通道的切换,共用一片7109由89C51控制,分时完成所有通道的采样与转换。 1.2 远程通讯电路    由于是远程数据采集系统,对数据传输的距离提出了较高的要求。PC机与单片机232C串行口直接相连,传输距离只有十几米,无法满足系统要求。为此采用 了一个RS232C到RS422A的转换装置,PC机与89C51间接相连,以RS422A方式进行通讯,大大增加了传输距离。   PC机与89C51串行通讯电路框图如图2所示。    RS422A是一种以平衡方式传输的标准,可双端发送、双端接收。发送端和接收端分别采用平衡发送及差动接收。通过前者把逻辑电平变成电位差,完成始端 信息传送;通过后者把电位差变成逻辑电平,完成终端信息接收。并且RS422A采用双线传输,大大提高了抗干扰能力。最大传输速率可达10 Mb/s(传输距离15 m时),传输速率降至90 kb/s时,最大传输距离可达1200 m,这能充分满足系统的“远程”要求。 2 软件设计   软件设计采用模块化程序设计方法,按功能分为4个模块,其中数据通信模块又分为单片机串行通信程序和PC机通信程序,除与PC机通信程序使用VC++编程,其余均采用汇编语言编制。 2.1 主程序模块   主程序主要完成对系统硬件电路的初始化,设置堆栈指针、串行口、T0、T1工作方式、8155显示指示符,扫描键盘获取键值并进行散转处理。主程序模块负责管理和调用各子模块。 《电子设计技术》网站版权所有,谢绝转载 2.2 数据采集模块   该模块完成对数据的采集及处理,中间调用了数字滤波子程序、数据转换子程序、字形转换及显示子程序等。 系统数据采样模块框图如图3所示。    系统上电即执行初始化程序。当操作员按下采样键时执行数据采样模块。从00~07通道间隔每秒采集每个通道的5个值,调用滤波子程序得到准确值,再通过 数据转换子程序分别送到6116数据区及8155RAM区,通过字形显示子程序显示各通道检测的数据。每采集完一个周期后,89C51单片机通过 MAX232接口PC机查询有无通信命令,有则响应,无则继续采集数据。该程序一直按框图流程循环执行,直至意外掉电或强迫复位后,才能终止数据采集。 2.3 故障诊断模块    数据采集过程中,若出现故障会直接影响采样结果,所得到的错误数据不允许存档,并应该记录故障原因及持续时间。故障诊断模块主要是89C51外围芯片 MAX691的电源监控以及掉电保护电路检测到硬件故障后向单片机发出中断请求INT0所执行的外部中断服务子程序。该程序主要功能是在累加数据保存完毕 后,置位89C51内部的特殊功能寄存器PCON中的PD,使RAM进入掉电模式,保护数据不变,同时显示故障类型和发生的时间。若为软件死循环引起的故 障,则MAX691的“看门狗”电路自动使程序跳出陷阱,强迫系统复位。 2.4 数据通信模块   分单片机通信程序和PC机通信程序。 2.4.1 单片机通信程序 流程图如图4所示。 《电子设计技术》网站版权所有,谢绝转载 2.4.2 Win98下PC机与89C51通信程序    通讯程序编写中首先在项目头文件中嵌入MSComm控件的头文件MSComm.h及实现文件MSComm.cpp,其次,为了用该控件控制一个串口的通 讯操作,还必须在相应程序中插入该控件。为此,设计在某对话框中插入MSComm控件,其ID为IDC_MSComm1,并利用ClassWizard 为其添加变量CCMSComm m_Com1,通讯程序中对串口的所有操作都可以通过m_Com1来实现。   89C51通过中断方式采集和传递数据。当其数据缓冲区满时,向CPU发出中断申请,若CPU响应并经与PC机握手后便可发送数据。因此PC机采用查询的通讯方式。设计中将PC机串口每接收一帧数据设置成串口要响应的事件EV_RXFLAG事件,通过此事件激活消息处理函数OnComm(),在OnComm()中加入处理代码,判断是否是所需的数据,再作出相应的显示、存盘等处理。   下面简要给出用事件驱动方式接收89C51单片机发送数据的程序源代码。通讯时PC机串口与89C51串口参数的设置必须一致,否则两者无法进行通讯。设置PC机串口参数的初始化程序如下: If(!m_Com1.getportOpen()) m_Com1.SetPortOpen(TRUE);//打开串口    m_Com1.SetSettings("9600,n,11,1"); //串口参数设置    m_Com1.InputMode(1); //建立1024字节输入队列    SetCommEvent(m_Com1,EV_RXFLAG); //设置串口要响应的事件EV_RXFLAG    m_Com1.SetRThreshold(200); //每接收200帧激活OnComm()事件 ……… 3 结束语    本文通过PC机与89C51单片机组成一简单的多机系统,通过串行通信实现了远程数据采集系统的基本功能。在硬件连接上,为提高传输距离,采用了RS- 232C/RS-422A转换电路,以差分传输、差分接受的形式解决了这一问题。在软件编制上,采用流行的VC++6.0下的Active X控件,通过对控件相关属性及代码的编写,实现了Windows 98环境下PC机与89C51单片机的远程通信。该方法也可以用于类似的工业场合中。 《电子设计技术》网站版权所有,谢绝转载
相关资源