简单的上位机串口控制单片机
测试使用上位机提供web服务,通过串口来控制单片机单片机使用STC8H8K64U,上位机使用的是golang语言,最终效果如下 单片机的程序可以参照,实现了简单的串口通信以及串口数据处理
STC8H8K64U-软件实现串口不断电烧录程序
串口数据处理函数中,如果收到hello 则返回world!,如果收到0x0f,则将P1端口设置为接收到的第二位数据
void DealString(char *p)
{
if(p == 0x0f)
{
P1 = p;
UartSendStr("p1");
}else if(strcmp(p,"p1")==0)
{
UartSend(P1);
}
else if(strcmp(p,"hello") == 0)
{
UartSendStr("world!");
}
else if(strcmp(p,"reboot") == 0)
{
Delay_ms(1000);
UartSendStr("bye!");
IAP_CONTR = 0x60;
}
else if(strncmp(p,"seg",3) == 0)
{
STC_SEG7_ShowString(p+3);
}
else if (strcmp(p,"led40") == 0)
{
Test_STC_LED40();
}
else
{
UartSendStr(p);
}
} 完整的单片机代码和golang源码: golang上封装下串口操作,使用github.com/jacobsa/go-serial/serial包,实现了打开串口,收发数据,以及关闭串口
package myfun
import (
"errors"
"io"
"github.com/jacobsa/go-serial/serial"
)
var _port io.ReadWriteCloser = nil
var _options = serial.OpenOptions{
PortName: "",
BaudRate: 19200,
DataBits: 8,
StopBits: 1,
MinimumReadSize: 4,
InterCharacterTimeout: 500,
}
func OpenPort(port_name string) error {
if _port != nil {
_port.Close()
}
var err error
_options.PortName = port_name
_port, err = serial.Open(_options)
if err != nil {
_port = nil
}
return err
}
func SendAndRecv(msg string) (string, error) {
if _port == nil {
return "", errors.New("请先打开串口")
}
bts := []byte(msg)
_, err := _port.Write(bts)
if err != nil {
return "", err
}
buff := make([]byte, 128)
n, err := _port.Read(buff)
if err != nil {
return "", err
}
return string(buff[:n]), nil
}
func SendAndRecv_bts(msg []byte) ([]byte, error) {
if _port == nil {
return nil, errors.New("请先打开串口")
}
_, err := _port.Write(msg)
if err != nil {
return nil, err
}
buff := make([]byte, 128)
_, err = _port.Read(buff)
if err != nil {
return nil, err
}
return buff, nil
}
func ClosePort() error {
if _port != nil {
return _port.Close()
}
return nil
}
使用gin搭建web服务,实现web调用打开串口,开灯,关灯和hello的响应
package myfun
import (
"fmt"
"github.com/gin-gonic/gin"
)
func _send(c *gin.Context, msg string) {
c.JSON(200, gin.H{
"msg": msg,
})
}
func Gin_OpenCom(c *gin.Context) {
com_name := c.Query("c")
if len(com_name) <= 0 {
_send(c, "COM口异常")
return
}
err := OpenPort(com_name)
if err == nil {
_send(c, "COM口打开成功!")
} else {
_send(c, err.Error())
}
}
func Gin_LedOn(c *gin.Context) {
_, err := SendAndRecv_bts([]byte{0x0f, 0x00})
if err != nil {
_send(c, err.Error())
} else {
_send(c, "开灯 - 操作成功")
}
}
func Gin_LedOff(c *gin.Context) {
_, err := SendAndRecv_bts([]byte{0x0f, 0xff})
if err != nil {
_send(c, err.Error())
} else {
_send(c, "关灯 - 操作成功")
}
}
func Gin_Hello(c *gin.Context) {
msg, err := SendAndRecv("hello")
fmt.Println(msg)
if err != nil {
_send(c, err.Error())
} else {
_send(c, msg)
}
}
简单写一个控制网页,使用XMLHttpRequest来后台发送获取数据
<!DOCTYPE html>
<html>
<head></head>
<body>
<div><p id="msg"></p></div>
<div>
串口:
<select id="com_select">
<option value="COM1">COM1</option>
<option value="COM2">COM2</option>
<option value="COM3">COM3</option>
<option value="COM4">COM4</option>
<option value="COM5">COM5</option>
<option value="COM6">COM6</option>
<option value="COM7">COM7</option>
<option value="COM8">COM8</option>
<option value="COM9">COM9</option>
</select>
<button id="com_btn" onclick="open_com()">打开串口</button>
</div>
<br />
<div>
<button id="hello_btn" onclick="hello()">hello</button>
<button id="led_open_btn" onclick="led_on()">开灯</button>
<button id="led_close_btn" onclick="led_off()">关灯</button>
</div>
<script type="text/javascript">
xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState==4 && xmlhttp.status==200)
{
var res = JSON.parse(xmlhttp.responseText)
document.getElementById("msg").innerText = res.msg;
}
}
function open_com(){
var v = document.getElementById("com_select").value
xmlhttp.open("GET","/open_com?c="+v,true)
xmlhttp.send()
}
function led_on(){
xmlhttp.open("GET","/led_on",true)
xmlhttp.send()
}
function led_off(){
xmlhttp.open("GET","/led_off",true)
xmlhttp.send()
}
function hello(){
xmlhttp.open("GET","/hello",true)
xmlhttp.send()
}
</script>
</body>
</html> 如果需要手机访问,可以修改主函数中gin监听的ip如下即可
func main() {
r := gin.Default()
r.GET("ping", pong)
r.GET("open_com", myfun.Gin_OpenCom)
r.GET("led_on", myfun.Gin_LedOn)
r.GET("led_off", myfun.Gin_LedOff)
r.GET("hello", myfun.Gin_Hello)
r.StaticFile("uart.html", "html/index.html")
r.Run(":12345")
fmt.Println("Hello")
} 手机上访问http://上位机ip:12345/uart.html则可进行控制了
页:
[1]
2