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.comqiniuiconv,
//
// iconv.go
//
package iconv
// #cgo darwin LDFLAGS: -liconv
// #cgo freebsd LDFLAGS: -liconv
// #cgo windows LDFLAGS: -liconv
// #include
// #include
// #include
//
// 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
#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)
}