C语言控制台程序模拟传感器实现UDP指令接收、数据查询、数据发送 sensor1.0

嵌入式系统课程的大作业,我负责的部分主要是sensor部分的控制台程序。记录一下这部分程序的主要内容和迭代过程。emmm第一次写这样的程序,真是状况百出,目前还是一个非常简陋的sensor…希望它以后能长成一个成熟的sensor吧
顺便记录一下遇到的一些错误和解决测试。希望能帮到大家呀。

主要功能&实现思路:

  • 接收workstation(另一个控制台程序)发送来的查询数据:
    通过相对比较简单的UDP实现程序间通信
  • 查询相应传感器的值
    定义一个传感器类型的结构体,里面预先存储大量实际传感器可能测得的值(比如温度传感器的值域数组里就存储36.5 36.7 等类似的数据,也可以以先把浮点数扩大十倍存储和传输,等传到了workstation再处理成小数),接收到查询的指令后,就去数组里随机取出一个数,来模拟实际传感器测量的过程。
  • 把查到的值返回给workstation

除此之外还需要

  • 需要有一个时钟控制动作发生的频率
    设置timer结构体:记录开始计时的时间,计时间隔和计时时间到达之后需要执行的回调函数,在主函数里循环判断各个计时器是否到达计时间隔如果到达就执行对应的回调函数
  • 需要有一个接收和发送队列,防止数据来不及处理被覆盖掉
    设置BYTEQUEUE结构体,实现一个数组队列,结构体包括一个指针指向数组的首地址,两个int类型的数值分别记录当前队首和队尾的数组下标。

sensor.h头文件

#include"stdio.h"
#include "time.h"
#include"winsock2.h"
#include"windows.h"
#include"malloc.h"
//winsock2.h的头文件需要放在windows.h前面否则会报错
#pragma comment (lib, "ws2_32.lib") 

int FLAG;//标志变量用于退出while循环

/***************************transducer_service传感器***********************************/
struct transducer {
	int id;//传感器编号
	char name[32];//传感器名称
	//int seed;//暂时不知道干啥用
	int value[512];//传感器值域
}trans[10];
struct transducer *ptrans;//
//初始化一个传感器
void init_trans_n(struct transducer trans[],int idn, char namen[32], int valuen[512]);
//初始化传感器组
void init_trans(struct transducer trans[]);
//读值
int read_trans(struct transducer trans[],int id);
//查找某个传感器
struct transducer get(struct transducer trans[],int id_n);



/**************************nioservice 队列接口定义********************************/
#define QUEUE_TYPE int //定义队列类型为int

struct BYTEQUEUE {
	QUEUE_TYPE *buf;
	int queue_size;//队列长度
	int front;//标记队头
	int rear;//标记队尾
}rxbuf, txbuf;
struct BYTEQUEUE *rxp;//= &rxbuf;
struct BYTEQUEUE *txp;//= &txbuf;

//创建队列
void open_queue( struct BYTEQUEUE *queue,int size);

//销毁队列
void close_queue(struct BYTEQUEUE *queue);

//往队尾放数 返回-1表示不成功 返回1表示成功
int pushback_queue(struct BYTEQUEUE *queue,QUEUE_TYPE value);

//删除队首数值,并返回该值
QUEUE_TYPE popfront_queue(struct BYTEQUEUE *queue);

//判断队列是否为空
int is_empty_queue(struct BYTEQUEUE *queue);

//判断队列是否已经满了
int is_full_queue(struct BYTEQUEUE *queue);

//返回队列第一个值
QUEUE_TYPE front_value_queue(struct BYTEQUEUE *queue);

//获取队列元素个数
int get_size_queue(struct BYTEQUEUE *queue);



/*****************************定时器timer和回调函数**********************************/
struct timer {
	int interval;//计时间隔
	time_t lasttime;//计时开始时间
	void(*pf)();//回调函数指针
}timer[10];

void init_timer(struct timer *pt);
//回调函数

//接受数据并存入rxbuf
void recv_data();
//查看传感器数值
void see_trans();
//从txbuf发送数据
void send_data();



void all();

/*****************************UDP******************************************/
#define BUF_SIZE 100

WSADATA wsaData;
//创建套接字
SOCKET sock ;
//绑定套接字
struct sockaddr_in servAddr;
//接收客户端请求
SOCKADDR clntAddr;  //客户端地址信息
int nSize;
char buffer[BUF_SIZE];  //缓冲区

//初始化 UDP通道;
void init_io();
//关闭UDP通道
void close_io();

主函数实现过程:

#include "sensor_console.h"
void main()
{
	init_trans(trans);
	init_io();
	rxp = &rxbuf;
	txp = &txbuf;
	open_queue(rxp,100);
	open_queue(txp,100);
	init_timer(timer);
	FLAG = 1;
	
	while(1)
	{
		for (int i = 3; i < 4; i++)
		{
			if (time(NULL) - timer[i].lasttime >= timer[i].interval)
			{
				timer[i].pf();
				timer[i].lasttime = time(NULL);
			}
			if (FLAG == -1)
				break;
		}
		if (FLAG==-1)
			break;
	}
	close_queue(rxp);
	close_queue(txp);
	close_io();
}

用于测试收发数据的test程序:(或者也可以说是一个极其简陋版的workstation,手动版)来源:http://c.biancheng.net/view/2359.html

#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
#define BUF_SIZE 100
int main() {
	//初始化DLL
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	//创建套接字
	SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
	//服务器地址信息
	struct sockaddr_in servAddr;
	memset(&servAddr, 0, sizeof(servAddr));  //每个字节都用0填充
	servAddr.sin_family = PF_INET;
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	servAddr.sin_port = htons(1234);
	//不断获取用户输入并发送给服务器,然后接受服务器数据
	struct sockaddr fromAddr;
	int addrLen = sizeof(fromAddr);
	while (1) {
		char buffer[BUF_SIZE] = { 0 };
		printf("Input a string: ");
		gets(buffer);
		int wer=sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
		printf("%d\n",wer);
		int strLen = recvfrom(sock, buffer, BUF_SIZE, 0, &fromAddr, &addrLen);
		buffer[strLen] = 0;
		printf("Message form server: %d \n", buffer[0]-48);
	}
	closesocket(sock);
	WSACleanup();
	return 0;
}

测试结果:
test:

Input a string: 2
Message form server: 55
Input a string: 1
Message form server: 47
Input a string: 0
Message form server: 38
Input a string: 2
Message form server: 59
Input a string: 1
Message form server: 46
Input a string: 2
Message form server: 57
Input a string:

sensor:

收到的数据为2
查询第2号传感器的数值
查得值为51
sended:51
收到的数据为2
查询第2号传感器的数值
查得值为55
sended:55
收到的数据为1
查询第1号传感器的数值
查得值为47
sended:47
收到的数据为0
查询第0号传感器的数值
查得值为38
sended:38
收到的数据为2
查询第2号传感器的数值
查得值为59
sended:59
收到的数据为1
查询第1号传感器的数值
查得值为46
sended:46
收到的数据为2
查询第2号传感器的数值
查得值为57
sended:57

实现过程中出现的一些状况:

  1. 关于结构体做函数参数
    如果把一个函数体作为参数传给函数,在这个函数里对结构体的值进行修改的话,当退出这个函数的时候结构体的值并不会发生修改。解决的办法是用结构体数组做函数参数,或者用结构体指针做函数参数,(我猜可能是,把结构体传给函数的时候,函数其实是复制了一份这个结构体,实际是对这个副本进行的操作…瞎猜的,不算数)

需要改进的地方:

  1. 数据类型统一,目前这个简陋的sensor在收发过程中用的是char 但内部处理的时候用的是int
  2. 提高通信系销量,目前只能实现收一个发一个,队列其实根本没有用起来。
  3. timer其实目前也没有用起来,收-》查-》发其实写在一个回调函数里了,所以现在就是相当于每一秒收查发一次。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值