sercom DHLi协议串口驱动使用说明

 
 fcntl函数
 定义函数 int fcntl(int fd, int cmd); 
  int fcntl(int fd, int cmd, long arg); 
  int fcntl(int fd, int cmd, struct flock *lock);
fcntl()针对(文件)描述符提供控制.参数fd 是被参数cmd操作(如下面的描述)的描述符.
  针对cmd的值,fcntl能够接受第三个参数int arg




read函数
ssize_t read[1]  (int fd, void *buf, size_t count);
成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0。
参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1。注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。
read函数返回时,返回值说明了buf中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count,例如:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0。
 
 memcpy函数
 c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
 
 fflush(stdout);强制输出,保证下一行的代码能得到一个完全清空完的缓冲区


 */


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>


#include <sercomm.h>//hdlc串口驱动


#include <osmocom/core/linuxlist.h>
#include <osmocom/core/select.h>
#include <osmocom/core/serial.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>


#include <arpa/inet.h>


#define MODEM_BAUDRATE B115200//串口波特率


struct osmo_fd serial_fd;//串口开关
struct osmo_fd console_fd;//console开关


static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len)//发送到电话的函数
{
struct msgb *msg;
uint8_t *dest;


if (len > 512) {//长度小于512字节
fprintf(stderr, "Too much data to send. %u\n", len);
return;
}


/* push the message into the stack */
msg = sercomm_alloc_msgb(512);
if (!msg) {
fprintf(stderr, "Failed to create data for the frame.\n");
return;
}


/* copy the data */
dest = msgb_put(msg, len);//转换为hdlc数据
memcpy(dest, data, len);


sercomm_sendmsg(dlci, msg);//发送函数


serial_fd.when |= BSC_FD_WRITE;//状态更变
}


static int handle_sercomm_write(void)
{
uint8_t buffer[256];
int i, count = 0, end = 0;


for (i = 0; i < sizeof(buffer); i++) {
if (sercomm_drv_pull(&buffer[i]) == 0) {//如果写入有0结束写入
end = 1;
break;
}
count++;
}


if (count) {
if (write(serial_fd.fd, buffer, count) != count)//写入串口数据超过256个
perror("short write");
}


if (end)
serial_fd.when &= ~BSC_FD_WRITE;//转换使能


return 0;
}


static uint8_t buffer[256];


static int handle_sercomm_read(void)
{
int nbytes, i;


nbytes = read(serial_fd.fd, buffer, sizeof(buffer));//从串口读数据
if (nbytes <= 0)
return nbytes;


for (i = 0; i < nbytes; ++i) {
if (sercomm_drv_rx_char(buffer[i]) == 0)//收到一个字节,通过sercomm,返回1的情况下,成功,0的情况下,未确认的字符
printf("Dropping sample '%c'\n", buffer[i]);//写入为0
}


return nbytes;
}


static int serial_cb(struct osmo_fd *fd, unsigned int flags)//第一循环
{
int rc;
if (flags & BSC_FD_READ) {//读使能
while ((rc = handle_sercomm_read()) > 0);
}


if (flags & BSC_FD_WRITE) {//写使能
rc = handle_sercomm_write();//这里写入的
}
return 0;
}


static char inputbuffer[256];
static char *inputptr = inputbuffer;


static int handle_console_read(void)//第三步
{
int nbytes;


again:
nbytes = read(console_fd.fd, inputptr, 1);//console命令输入1字,并且传输给inputpter
if (nbytes <= 0)//限制
return nbytes;
inputptr++;


if ((inputptr - inputbuffer) == sizeof(inputbuffer)-1
|| inputptr[-1] == '\n') {//检测回车
*inputptr = '\0';
hdlc_send_to_phone(SC_DLCI_CONSOLE, (uint8_t *)inputbuffer,
strlen(inputbuffer)-1);//第四步
inputptr = inputbuffer;
}


goto again;//继续循环
}


static int console_cb(struct osmo_fd *fd, unsigned int flags)
{
int rc;
if (flags & BSC_FD_READ) {//读使能
while ((rc = handle_console_read()) > 0);//第二步
// if (rc == 0)
// exit(2);
}


return 0;
}




static void hdlc_console_cb(uint8_t dlci, struct msgb *msg)//HDLC接口函数函数
{
int rc;


rc = write(1, msg->data, msg->len);//从hdlc收到的数据转为date,长度为len。这两个是全局都有用的
fflush(stdout);//强制输出
msgb_free(msg);//释放msg
}


#define HELP_TEXT \
"[ -v | -h ] [ -p /dev/ttyXXXX ]\n"


static int usage(const char *name)//打印help
{
printf("Usage: %s ", name);
printf(HELP_TEXT);
exit(2);
}


static int version(const char *name)//答应版本
{
printf("%s version %s\n", name, PACKAGE_VERSION);
exit(2);
}


int main(int argc, char **argv)//主函数
{
int opt, flags;
const char *serial_dev = "/dev/ttyUSB1";//默认打开的串口


while ((opt = getopt(argc, argv, "hp:v")) != -1) {//打开命令行参数输入
switch (opt) {
case 'p':
serial_dev = optarg;
break;
case 'v':
version(argv[0]);
break;
case 'h':
default:
usage(argv[0]);
break;
}
}


serial_fd.fd = osmo_serial_init(serial_dev, MODEM_BAUDRATE);//串口初始化
if (serial_fd.fd < 0) {
fprintf(stderr, "Cannot open serial device %s\n", serial_dev);
exit(1);
}


if (osmo_fd_register(&serial_fd) != 0) {//把系统串口注册到osmo_fd_register驱动里去
fprintf(stderr, "Failed to register the serial.\n");
exit(1);
}


/* Set serial socket to non-blocking mode of operation 设置串口socket为non-bloacking(非阻塞模式)*/
flags = fcntl(serial_fd.fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(serial_fd.fd, F_SETFL, flags);


serial_fd.when = BSC_FD_READ;//使能读
serial_fd.cb = serial_cb;//缓存


console_fd.fd = 0;//设置FD缓冲为0


if (osmo_fd_register(&console_fd) != 0) {//串口注册console模式
fprintf(stderr, "Failed to register the serial.\n");
exit(1);
}


console_fd.when = BSC_FD_READ;
console_fd.cb = console_cb;//循环起点


/* initialize the HDLC layer */
sercomm_init();
sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb);//注册console,函数hdlc_console_cb


while (1) {
if (osmo_select_main(0) < 0)
break;
}


close(serial_fd.fd);


exit(0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值