嵌入式linux之go语言开发(二)c动态库驱动调用

简介: 嵌入式linux之go语言开发(二)c动态库驱动调用

c的代码及动态库调用:


最终需要完成的封装有:串口驱动,扫码模块,语音播放库,UI显示库,卡库...


一、串口及扫码模块驱动:


linux上的串口驱动,这个较简单,有标准的模块可用。操作的是标准的设备文件。如:ttys0等。


在B503机器上,串口和二维码扫码模块。都用到了标准的linux串口。只不过二维码模块的供电需要先开启IO口


这个已经验证,串口和二维码的串口都是ok了。可以使用。


func exec_shell(s string) {
  cmd := exec.Command("/bin/bash", "-c", s)
  var out bytes.Buffer
  cmd.Stdout = &out
  err := cmd.Run()
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("%s", out.String())
}
func Initserial() {
  fmt.Println("init serial...")
  exec_shell("./enGPIO.sh")
  //cmd := exec.Command("ls")
  //开启二维码模块电源
  d := `echo "1"   > "/sys/class/gpio/gpio121/value"`
  cmd := exec.Command("sh", "-c", d)
  var out bytes.Buffer
  cmd.Stdout = &out
  err := cmd.Run()
  if err != nil {
    log.Printf("failed to exec cmd")
    log.Printf(err.Error())
  } else {
    log.Println(out.String())
  }
  fmt.Println("init serial ok")
}


    //设置串口编号
  c := new(serial.Config)
  c.Name = "/dev/ttymxc5"
  c.Baud = 115200
  c.ReadTimeout = 0
  //打开串口
  s, err := serial.OpenPort(c)
  if err != nil {
    log.Printf("failed to open serial port")
    log.Fatal(err)
  }
  fmt.Println("open serial port ok! ")


root@b503_lcd:/app/city_app/opt# ./serial
Hello Go
shell exec open...
shell exec over.
2018/11/03 11:48:18
press any key to continue:
open serial port ok!
2018/11/03 11:48:20 <-waite for receive..
monitorLoop..modeb(1) sim card is not exist,please put in sim card!!!
2018/11/03 11:48:50 <-收到串口信息,len=21
2018/11/03 11:48:50 363232373239323838383932303636343737320d0a
2018/11/03 11:48:52 <-收到串口信息,len=21


二、语音模块驱动


语音模块涉及到的头文件为pcm-ctrl.h,动态库为libpcmctrl.so



调用demo:


package main
/*
#cgo CFLAGS: -Iinclude
#cgo LDFLAGS: -Llib -lpcmctl -lasound
#include "pcm-ctl.h"
*/
import "C"
import (
  "bytes"
  "fmt"
  "log"
  "os/exec"
)
func exec_shell(s string) {
  cmd := exec.Command("/bin/bash", "-c", s)
  var out bytes.Buffer
  cmd.Stdout = &out
  err := cmd.Run()
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("%s", out.String())
}
func InitSys() {
  fmt.Println("init sys...")
  exec_shell("./enGPIO.sh")
  //cmd := exec.Command("ls")
  //开启二维码模块电源
  d := `echo "1"   > "/sys/class/gpio/gpio121/value"`
  cmd := exec.Command("sh", "-c", d)
  var out bytes.Buffer
  cmd.Stdout = &out
  err := cmd.Run()
  if err != nil {
    log.Printf("failed to exec cmd")
    log.Printf(err.Error())
  } else {
    log.Println(out.String())
  }
  fmt.Println("init sys ok")
}
func PlayVoice(name string) int {
  cmd := C.CString(name)
  ret := C.play_wav(cmd, 5)
  if ret == 0 {
    log.Printf("play voice ok")
  } else {
    log.Printf("play voice err")
  }
  return int(ret)
}
func main() {
  fmt.Println("Hello Go")
  InitSys()
  PlayVoice("./Welcome.wav")
  name := ""
  fmt.Println("over!press any key to continue: ")
  fmt.Scanln(&name)
}


root@b503_lcd:/app/city_app/opt# ./voice
Hello Go
init sys...
shell exec open...
shell exec over.
2018/11/03 12:23:13
init sys ok
2018/11/03 12:23:14 play voice ok
over!press any key to continue:


三、界面显示模块调用:


界面模块调用libucgui.so,其中遇到了一些问题,最后也一一解决了,比如如何向go传递结构体等,


UTF8汉字编码转gbk


其中uf8转gbk,使用libiconv和七牛的iconv-go都报错,不能转换成功。


一开始以为是板子上没有libconv所致,找了份libconv的源码交叉编译后放心去还不行,仍是提示:


iconv.Open failed!


iconv.Open failed!


打开源码看看他里面有什么,


github.com\qiniu\iconv,


//
// iconv.go
//
package iconv
// #cgo darwin  LDFLAGS: -liconv
// #cgo freebsd LDFLAGS: -liconv
// #cgo windows LDFLAGS: -liconv
// #include <iconv.h>
// #include <stdlib.h>
// #include <errno.h>
//
// size_t bridge_iconv(iconv_t cd,
//           char *inbuf, size_t *inbytesleft,
//                     char *outbuf, size_t *outbytesleft) {
//   return iconv(cd, &inbuf, inbytesleft, &outbuf, outbytesleft);
// }
import "C"
import (
  "bytes"
  "io"
  "syscall"
  "unsafe"
)
var EILSEQ = syscall.Errno(C.EILSEQ)
var E2BIG = syscall.Errno(C.E2BIG)
const DefaultBufSize = 4096
type Iconv struct {
  Handle C.iconv_t
}
// Open returns a conversion descriptor cd, cd contains a conversion state and can not be used in multiple threads simultaneously.
func Open(tocode string, fromcode string) (cd Iconv, err error) {
  tocode1 := C.CString(tocode)
  defer C.free(unsafe.Pointer(tocode1))
  fromcode1 := C.CString(fromcode)
  defer C.free(unsafe.Pointer(fromcode1))
  ret, err := C.iconv_open(tocode1, fromcode1)
  if err != nil {
    return
  }
  cd = Iconv{ret}
  return
}
func (cd Iconv) Close() error {
  _, err := C.iconv_close(cd.Handle)
  return err
}
func (cd Iconv) Conv(b []byte, outbuf []byte) (out []byte, inleft int, err error) {
  outn, inleft, err := cd.Do(b, len(b), outbuf)
  if err == nil || err != E2BIG {
    out = outbuf[:outn]
    return
  }
  w := bytes.NewBuffer(nil)
  w.Write(outbuf[:outn])
  inleft, err = cd.DoWrite(w, b[len(b)-inleft:], inleft, outbuf)
  if err != nil {
    return
  } else {
    out = w.Bytes()
  }
  return
}
func (cd Iconv) ConvString(s string) string {
  var outbuf [512]byte
  if s1, _, err := cd.Conv([]byte(s), outbuf[:]); err != nil {
    return ""
  } else {
    return string(s1)
  }
}
func (cd Iconv) Do(inbuf []byte, in int, outbuf []byte) (out, inleft int, err error) {
  if in == 0 {
    return
  }
  inbytes := C.size_t(in)
  inptr := &inbuf[0]
  outbytes := C.size_t(len(outbuf))
  outptr := &outbuf[0]
  _, err = C.bridge_iconv(cd.Handle,
    (*C.char)(unsafe.Pointer(inptr)), &inbytes,
    (*C.char)(unsafe.Pointer(outptr)), &outbytes)
  out = len(outbuf) - int(outbytes)
  inleft = int(inbytes)
  return
}
func (cd Iconv) DoWrite(w io.Writer, inbuf []byte, in int, outbuf []byte) (inleft int, err error) {
  if in == 0 {
    return
  }
  inbytes := C.size_t(in)
  inptr := &inbuf[0]
  for inbytes > 0 {
    outbytes := C.size_t(len(outbuf))
    outptr := &outbuf[0]
    _, err = C.bridge_iconv(cd.Handle,
      (*C.char)(unsafe.Pointer(inptr)), &inbytes,
      (*C.char)(unsafe.Pointer(outptr)), &outbytes)
    w.Write(outbuf[:len(outbuf)-int(outbytes)])
    if err != nil && err != E2BIG {
      return int(inbytes), err
    }
  }
  return 0, nil
}


通过源码可以看出,这种转码方案,底层是调的c的库,libconv。那么,它跟环境和系统就有关系了。不太通用。


感觉网上使用libconv库的转码方案,受限于环境,不太好用。没时间再去找原因了,于是换了一种库


最终的解决办法是:使用Mahonia,字符编解码库解决 UTF8转gbk编码问题。


https://github.com/axgle/mahonia


Go中实现的字符集转换库。


Mahonia是Go中实现的字符集转换库。所有数据都被编译成可执行文件; 它不需要任何外部数据文件。


基于http://code.google.com/p/mahonia/


root@b503_lcd:/app/city_app/opt# ./display


Hello Go


480, 272, 16


display test ok....


over!press any key to continue:


package drivers
/*
#cgo CFLAGS: -Iinclude/header
#cgo LDFLAGS: -Llib -lucgui -lm
#include <stdlib.h>
#include "GUI.h"
//extern const GUI_FONT GUI_FontHZ12;
extern const GUI_FONT GUI_FontHZ20x20;
extern const GUI_FONT GUI_FontHZ32x32;
extern const GUI_FONT GUI_FontHZ76x76;
extern void GUIcache2fb(void);
extern int setGUIcache(unsigned char sta);
extern unsigned char getGUIcache(void);
*/
import "C"
import "unsafe"
import (
  "github.com/axgle/mahonia"
)
var (
  //GUI_FontHZ12    C.GUI_FONT
  GUI_FontHZ20x20 *C.GUI_FONT
  GUI_FontHZ32x32 *C.GUI_FONT
  GUI_FontHZ76x76 *C.GUI_FONT
  GUI_FONT_8_ASCII *C.GUI_FONT
  GUI_FONT_8_1        *C.GUI_FONT
  GUI_FONT_10S_ASCII  *C.GUI_FONT
  GUI_FONT_10S_1      *C.GUI_FONT
  GUI_FONT_10_ASCII   *C.GUI_FONT
  GUI_FONT_10_1       *C.GUI_FONT
  GUI_FONT_13_ASCII   *C.GUI_FONT
  GUI_FONT_13_1       *C.GUI_FONT
  GUI_FONT_13B_ASCII  *C.GUI_FONT
  GUI_FONT_13B_1      *C.GUI_FONT
  GUI_FONT_13H_ASCII  *C.GUI_FONT
  GUI_FONT_13H_1      *C.GUI_FONT
  GUI_FONT_13HB_ASCII *C.GUI_FONT
  GUI_FONT_13HB_1     *C.GUI_FONT
  GUI_FONT_16_ASCII   *C.GUI_FONT
  GUI_FONT_16_1       *C.GUI_FONT
  GUI_FONT_16_HK      *C.GUI_FONT
  GUI_FONT_16_1HK     *C.GUI_FONT
  GUI_FONT_16B_ASCII  *C.GUI_FONT
  GUI_FONT_16B_1      *C.GUI_FONT
  // GUI_FONT_20_ASCII   *C.GUI_FONT
  // GUI_FONT_20_1       *C.GUI_FONT
  // GUI_FONT_20B_ASCII  *C.GUI_FONT
  // GUI_FONT_20B_1      *C.GUI_FONT
  GUI_FONT_24_ASCII  *C.GUI_FONT
  GUI_FONT_24_1      *C.GUI_FONT
  GUI_FONT_24B_ASCII *C.GUI_FONT
  GUI_FONT_24B_1     *C.GUI_FONT
  GUI_FONT_32_ASCII  *C.GUI_FONT
  GUI_FONT_32_1      *C.GUI_FONT
  GUI_FONT_32B_ASCII *C.GUI_FONT
  GUI_FONT_32B_1     *C.GUI_FONT
)
const (
  //================
  GUI_TEXTMODE_NORMAL C.int = C.GUI_TEXTMODE_NORMAL
  GUI_TEXTMODE_XOR    C.int = C.GUI_TEXTMODE_XOR
  GUI_TEXTMODE_TRANS  C.int = C.GUI_TEXTMODE_TRANS
  GUI_TEXTMODE_REV    C.int = C.GUI_TEXTMODE_REV
  GUI_TM_NORMAL       C.int = C.GUI_TM_NORMAL
  GUI_TM_XOR          C.int = C.GUI_TM_XOR
  GUI_TM_TRANS        C.int = C.GUI_TM_TRANS
  GUI_TM_REV          C.int = C.GUI_TM_REV
  //===================
  GUI_BLUE         C.uint = C.GUI_BLUE
  GUI_GREEN        C.uint = C.GUI_GREEN
  GUI_RED          C.uint = C.GUI_RED
  GUI_CYAN         C.uint = C.GUI_CYAN
  GUI_MAGENTA      C.uint = C.GUI_MAGENTA
  GUI_YELLOW       C.uint = C.GUI_YELLOW
  GUI_LIGHTBLUE    C.uint = C.GUI_LIGHTBLUE
  GUI_LIGHTGREEN   C.uint = C.GUI_LIGHTGREEN
  GUI_LIGHTRED     C.uint = C.GUI_LIGHTRED
  GUI_LIGHTCYAN    C.uint = C.GUI_LIGHTCYAN
  GUI_LIGHTMAGENTA C.uint = C.GUI_LIGHTMAGENTA
  GUI_LIGHTYELLOW  C.uint = C.GUI_LIGHTYELLOW
  GUI_DARKBLUE     C.uint = C.GUI_DARKBLUE
  GUI_DARKGREEN    C.uint = C.GUI_DARKGREEN
  GUI_DARKRED      C.uint = C.GUI_DARKRED
  GUI_DARKCYAN     C.uint = C.GUI_DARKCYAN
  GUI_DARKMAGENTA  C.uint = C.GUI_DARKMAGENTA
  GUI_DARKYELLOW   C.uint = C.GUI_DARKYELLOW
  GUI_WHITE        C.uint = C.GUI_WHITE
  GUI_LIGHTGRAY    C.uint = C.GUI_LIGHTGRAY
  GUI_GRAY         C.uint = C.GUI_GRAY
  GUI_DARKGRAY     C.uint = C.GUI_DARKGRAY
  GUI_BLACK        C.uint = C.GUI_BLACK
  GUI_BROWN        C.uint = C.GUI_BROWN
  GUI_ORANGE       C.uint = C.GUI_ORANGE
  GUI_TRANSPARENT  C.uint = C.GUI_TRANSPARENT
  TOP_BAR_COLOR C.uint = 0x501f08
)
func init() {
  //GUI_FontHZ12 = C.GUI_FontHZ12
  GUI_FontHZ20x20 = &C.GUI_FontHZ20x20
  GUI_FontHZ32x32 = &C.GUI_FontHZ32x32
  GUI_FontHZ76x76 = &C.GUI_FontHZ76x76
  GUI_FONT_8_1 = &C.GUI_Font8_1
  GUI_FONT_10S_ASCII = &C.GUI_Font10S_ASCII
  GUI_FONT_10S_1 = &C.GUI_Font10S_1
  GUI_FONT_10_ASCII = &C.GUI_Font10_ASCII
  GUI_FONT_10_1 = &C.GUI_Font10_1
  GUI_FONT_13_ASCII = &C.GUI_Font13_ASCII
  GUI_FONT_13_1 = &C.GUI_Font13_1
  GUI_FONT_13B_ASCII = &C.GUI_Font13B_ASCII
  GUI_FONT_13B_1 = &C.GUI_Font13B_1
  GUI_FONT_13H_ASCII = &C.GUI_Font13H_ASCII
  GUI_FONT_13H_1 = &C.GUI_Font13H_1
  GUI_FONT_13HB_ASCII = &C.GUI_Font13HB_ASCII
  GUI_FONT_13HB_1 = &C.GUI_Font13HB_1
  GUI_FONT_16_ASCII = &C.GUI_Font16_ASCII
  GUI_FONT_16_1 = &C.GUI_Font16_1
  GUI_FONT_16_HK = &C.GUI_Font16_HK
  GUI_FONT_16_1HK = &C.GUI_Font16_1HK
  GUI_FONT_16B_ASCII = &C.GUI_Font16B_ASCII
  GUI_FONT_16B_1 = &C.GUI_Font16B_1
  //GUI_FONT_20_ASCII   = &C.GUI_Font20_ASCII
  //GUI_FONT_20_1       = &C.GUI_Font20_1
  //GUI_FONT_20B_ASCII  = &C.GUI_Font20B_ASCII
  //GUI_FONT_20B_1      = &C.GUI_Font20B_1
  GUI_FONT_24_ASCII = &C.GUI_Font24_ASCII
  GUI_FONT_24_1 = &C.GUI_Font24_1
  GUI_FONT_24B_ASCII = &C.GUI_Font24B_ASCII
  GUI_FONT_24B_1 = &C.GUI_Font24B_1
  GUI_FONT_32_ASCII = &C.GUI_Font32_ASCII
  GUI_FONT_32_1 = &C.GUI_Font32_1
  GUI_FONT_32B_ASCII = &C.GUI_Font32B_ASCII
  GUI_FONT_32B_1 = &C.GUI_Font32B_1
}
func GUI_Init() {
  C.GUI_Init()
}
func GUI_Clear() {
  C.GUI_Clear()
}
func GUI_SetColor(val C.uint) {
  C.GUI_SetColor(C.ulong(val))
}
func GUI_SetBkColor(val C.uint) {
  C.GUI_SetBkColor(C.ulong(val))
}
func GUI_SetFont(val *C.struct_GUI_FONT) {
  C.GUI_SetFont(val)
}
//注:go中的编码为utf-8,GUI显示汉字使用的GB2312
func GUI_DispStringAt(str string, x, y int) {
  enc := mahonia.NewEncoder("gbk")
  gbk := enc.ConvertString(str)
  cs := C.CString(gbk)
  defer C.free(unsafe.Pointer(cs))
  C.GUI_DispStringAt(cs, C.int(x), C.int(y))
}
func GUI_DispStringHCenterAt(str string, x, y int) {
  enc := mahonia.NewEncoder("gbk")
  gbk := enc.ConvertString(str)
  cs := C.CString(gbk)
  defer C.free(unsafe.Pointer(cs))
  C.GUI_DispStringHCenterAt(cs, C.int(x), C.int(y))
}
func GUI_FillRect(x0, y0, x1, y1 int) {
  C.GUI_FillRect(C.int(x0), C.int(y0), C.int(x1), C.int(y1))
}
func GUI_SetTextMode(mode C.int) {
  C.GUI_SetTextMode(mode)
}
func GUIcache2fb() {
  C.GUIcache2fb()
}
func SetGUIcache(sta int) {
  C.setGUIcache(C.uchar(sta))
}
func GetGUIcache() int {
  return int(C.getGUIcache())
}
func main() {
  fmt.Println("Hello Go")
  GUI_Init()
  GUI_SetBkColor(0x954816)
  GUI_Clear()
  GUI_SetFont(&C.GUI_FontHZ20x20)
  GUI_DispStringAt("PRICE", 60, 156)
  GUI_DispStringAt("票价", 60, 120)
  name := ""
  fmt.Println("over!press any key to continue: ")
  fmt.Scanln(&name)
}


相关文章
|
4月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
248 61
|
8月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
2月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
2月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
3月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
3月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
261 0
|
4月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
5月前
|
Ubuntu 搜索推荐 Linux
详解Ubuntu的strings与grep命令:Linux开发的实用工具。
这就是Ubuntu中的strings和grep命令,透明且强大。我希望你喜欢这个神奇的世界,并能在你的Linux开发旅程上,通过它们找到你的方向。记住,你的电脑是你的舞台,在上面你可以做任何你想做的事,只要你敢于尝试。
291 32
|
7月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
1401 77
|
5月前
|
分布式计算 Go C++
初探Go语言RPC编程手法
总的来说,Go语言的RPC编程是一种强大的工具,让分布式计算变得简单如同本地计算。如果你还没有试过,不妨挑战一下这个新的编程领域,你可能会发现新的世界。
124 10