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


相关文章
|
8天前
|
关系型数据库 Go 网络安全
go语言中PostgreSQL驱动安装
【11月更文挑战第2天】
38 5
|
8天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
23 4
|
16天前
|
Go 数据安全/隐私保护 开发者
Go语言开发
【10月更文挑战第26天】Go语言开发
32 3
|
17天前
|
Java 程序员 Go
Go语言的开发
【10月更文挑战第25天】Go语言的开发
26 3
|
3月前
|
Java Linux API
Linux设备驱动开发详解2
Linux设备驱动开发详解
43 6
|
3月前
|
消息中间件 算法 Unix
Linux设备驱动开发详解1
Linux设备驱动开发详解
49 5
|
3月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
|
3月前
|
Ubuntu NoSQL Linux
Linux内核和驱动
Linux内核和驱动
29 2
|
3月前
|
数据采集 Linux
Linux源码阅读笔记20-PCI设备驱动详解
Linux源码阅读笔记20-PCI设备驱动详解
|
2月前
|
Linux API
Linux里的高精度时间计时器(HPET)驱动 【ChatGPT】
Linux里的高精度时间计时器(HPET)驱动 【ChatGPT】