嵌入式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)
}


相关文章
|
1天前
|
Linux C++
Linux C/C++动态库制作
Linux C/C++动态库制作
|
2天前
|
物联网 Linux 芯片
学习嵌入式是选择单片机还是Linux?
单片机通常指的是一种集成了处理器、存储器和各种外设接口的微控制器芯片,常见的有STC、51系列、AVR、ARM Cortex-M等。单片机具有低成本、低功耗、实时性强等特点,适用于对资源要求较低、功耗要求较低、实时性要求较高的嵌入式系统。学习单片机开发可以让您深入了解嵌入式系统的底层原理和硬件编程,对于对嵌入式系统底层开发感兴趣的人来说,是一个很好的选择。
10 4
|
5天前
|
Linux 编解码 Python
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
AV1是一种高效免费的视频编码标准,由AOM联盟制定,相比H.265压缩率提升约27%。各大流媒体平台倾向使用AV1。本文介绍了如何在Linux环境下为FFmpeg集成AV1编解码库libaom、libdav1d和libsvtav1。涉及下载源码、配置、编译和安装步骤,包括设置环境变量以启用这三个库。
31 3
FFmpeg开发笔记(二十四)Linux环境给FFmpeg集成AV1的编解码器
|
18天前
|
运维 网络协议 Linux
2024年最全CentOS8 Consul微服务架构安装(1)_agent(1),Linux运维开发面试
2024年最全CentOS8 Consul微服务架构安装(1)_agent(1),Linux运维开发面试
|
19天前
|
编解码 Linux 5G
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
AVS3,中国制定的第三代音视频标准,是首个针对8K和5G的视频编码标准,相比AVS2和HEVC性能提升约30%。uavs3d是AVS3的解码器,支持8K/60P实时解码,且在各平台有优秀表现。要为FFmpeg集成AVS3解码器libuavs3d,需从GitHub下载最新源码,解压后配置、编译和安装。之后,重新配置FFmpeg,启用libuavs3d并编译安装,通过`ffmpeg -version`确认成功集成。
32 0
FFmpeg开发笔记(二十)Linux环境给FFmpeg集成AVS3解码器
|
21天前
|
运维 监控 关系型数据库
【Zabbix 6(1),Linux运维组件化开发教程
【Zabbix 6(1),Linux运维组件化开发教程
|
23天前
|
Linux vr&ar C语言
|
23天前
|
Linux C语言
|
23天前
|
存储 Linux 编译器
【Linux】详解动态库链接和加载&&对可执行程序底层的理解
【Linux】详解动态库链接和加载&&对可执行程序底层的理解
|
23天前
|
存储 Linux 编译器
【探索Linux】P.13(文件系统 | 软硬链接 | 动态库和静态库)
【探索Linux】P.13(文件系统 | 软硬链接 | 动态库和静态库)
17 0