C51汇编典型代码&一些org-mode技巧
具体内容可见存放的数据。
下面主要介绍关键代码。
ASM 部分
1;; LCD数据发送============================================================= 2OUT_DATA: 3 PUSH 01H 4 PUSH 02H 5 PUSH 03H 6 MOV R2, #32 ;32行,(双屏结构中上半屏) 7 MOV R3, #80H ;Y地址寄存器 8LCD_ADDR_UP: 9 MOV SONG, R3 ;设置绘图区的Y地址坐标10 INC R3 ;Y地址加111 LCALL SEND_ML12 MOV SONG, #80H ;设置绘图区的X地址坐标13 LCALL SEND_ML14 MOV R1, #16 ;16*8列15LCD_DISP_UP:16 CLR A17 MOVC A, @A+DPTR18 MOV SONG, A19 LCALL SEND_SJ20 INC DPTR21 DJNZ R1, LCD_DISP_UP22 DJNZ R2, LCD_ADDR_UP ;写满全屏的16*8字节X6423 MOV R2, #32 ;32行,(双屏结构的下半屏)24 MOV R3, #80H ;Y地址寄存器25LCD_ADDR_DOWN:26 MOV SONG, R3 ;设置绘图区的Y地址坐标27 INC R3 ;Y地址加128 LCALL SEND_ML29 MOV SONG, #88H ;设置绘图区的X地址坐标30 LCALL SEND_ML31 MOV R1, #16 ;16*8列32LCD_DISP_DOWN:33 CLR A34 MOVC A, @A+DPTR35 MOV SONG, A36 LCALL SEND_SJ37 INC DPTR38 DJNZ R1, LCD_DISP_DOWN39 DJNZ R2, LCD_ADDR_DOWN ;写满全屏的16*8字节X6440 POP 03H41 POP 02H42 POP 01H43 RET
这部分介绍了如何在 LCD12864 上进行绘图操作。
值得纪念的是,这部分代码是我自己摸索,对比着网上找来的资料,不断地调整,最后终于搞定的。
开心的是,分享给了其他人,表现顽强
目前还没学会如何在 org-mode 中直接插入网络图片,并且可以直接显示。。
python 部分
1import binascii 2import serial 3from time import sleep 4import matplotlib.pyplot as plt 5import matplotlib.animation as animation 6 7 8#初始数据绘图 9def update(frame):10 #读入模拟11 read_string = binascii.hexlify(ser.read()).decode('ascii')12 a = (int(read_string[0], 16) * 16 + int(read_string[1], 16))13 print(a)14 sleep(0.1)15 #绘图数据生成16 del(data_read[0])17 data_read.append(a)18 #绘图19 line.set_ydata(data_read)20 #颜色设置21 if abs(a) >= 40:22 plt.setp(line, 'color', 'r', 'linewidth', 2.0)23 else:24 plt.setp(line, 'color', 'b', 'linewidth', 2.0)25 return line2627if __name__ == '__main__':28 data_read = list(range(100))29 fig, ax = plt.subplots()30 line, = ax.plot(data_read)31 ax.set_ylim(0, 100)32 plt.grid(True)33 ax.set_ylabel("Temperature: ℃")34 ax.set_xlabel("Relative Time: s")3536 ser = serial.Serial(port='COM3', baudrate=1200)37 ani = animation.FuncAnimation(fig, update, frames=None, interval=100)38 plt.show()39ser.close()
这段代码中使用了 matplotlib.animation 这个特殊的子模块,用来绘制动态图。
最开始用的是 Tkinter 来配合 matplotlib 显示串口数据的状态,但是不适合大量数据连续的绘制。会出现卡死的状态。
直到最后,还是放弃了自定义界面的想法,干脆只是单纯的做图,于是有了这个版本。
但是还是要记录下之前的努力,下面的是原来的基于 Tkinter 和 matplotlib 的代码。
1# coding:utf-8 2""" 3实现读取端口数据实现绘图 42018年5月30日23:39:32 5""" 6import binascii 7import time 8from tkinter import * 9 10import matplotlib 11import serial 12from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 13from matplotlib.backend_bases import key_press_handler 14from matplotlib.figure import Figure 15 16 17def drawPic(): 18 """ 19 获取GUI界面设置的参数,利用该参数绘制图片 20 """ 21 # 清空图像,以使得前后两次绘制的图像不会重叠 22 screen_draw.clf() 23 add_plot = screen_draw.add_subplot(111) 24 add_plot.axis([0, 100, 00, 100]) 25 26 x = list(range(100)) 27 y = data_read 28 add_plot.plot(x, y, 'r', label='Temperature') 29 add_plot.set_title('DRAW') 30 canvas_draw.draw() 31 32 33def serial_data(): 34 """处理串口数据""" 35 # 打开端口 36 try: 37 port = input_port.get() 38 baudrate = int(input_baudrate.get()) 39 except: 40 port = 'COM3' 41 baudrate = 9600 42 input_port.delete(0) 43 input_baudrate.delete(0) 44 input_port.insert(0, 'COM3') 45 input_baudrate.insert(0, '9600') 46 47 ser = serial.Serial(port, baudrate) 48 list_index = list(range(50)) 49 data_read[0: 50] = data_read[50: 100] 50 for x in list_index: 51 read_string = binascii.hexlify(ser.read()).decode('ascii') 52 data_read[x + 50] = int(read_string[0], 16) * \ 53 16 + int(read_string[1], 16) 54 print(data_read[x]) 55 print("Over") 56 ser.close() 57 58 59def now_draw(): 60 """实时绘制图像""" 61 try: 62 port = input_port.get() 63 baudrate = int(input_baudrate.get()) 64 delay = int(input_delay.get()) 65 except: 66 port = 'COM3' 67 baudrate = 9600 68 delay = 10 69 input_port.delete(0) 70 input_baudrate.delete(0) 71 input_delay.delete(0) 72 input_port.insert(0, 'COM3') 73 input_baudrate.insert(0, '9600') 74 input_delay.insert(0, '10') 75 76 list_index_draw = list(range(100)) 77 ser = serial.Serial(port, baudrate) 78 79 start = time.clock() 80 81 while True: 82 read_string = binascii.hexlify(ser.read()).decode('ascii') 83 data_read[99] = int(read_string[0], 16) * 16 + int(read_string[1], 16) 84 data_read[0: 99] = data_read[1: 100] 85 86 drawPic() 87 88 # 指定退出死循环方式 89 if(data_read[99] == 85): # 温度采集模块关闭后,串口传回来的值就是 55H = 85 90 break 91 elif(delay > 0): 92 if(time.clock() - start >= delay): 93 break 94 95 ser.close() 96 97 98def on_key_event(event): 99 print('推出程序 %s' % event.key)100 root.quit()101 root.destroy()102103104if __name__ == '__main__':105 matplotlib.use('TkAgg')106107 # 用于接受数据的存储108 data_read = list(range(100))109 root = Tk()110111 # 在Tk的GUI上放置一个画布,并用.grid()来调整布局112 screen_draw = Figure(figsize=(5, 4), dpi=100)113 canvas_draw = FigureCanvasTkAgg(screen_draw, master=root)114 # 绑定任意键退出115 canvas_draw.mpl_connect('key_press_event', on_key_event)116117 canvas_draw.get_tk_widget().grid(row=0, columnspan=3)118 canvas_draw.draw()119120 # 放置标签、文本框和按钮等部件,并设置文本框的默认值和按钮的事件函数121 Label(root, text='请输入监测时长(s),0则无限,关闭测温即可停止:').grid(row=1, column=0)122 input_delay = Entry(root)123 input_delay.grid(row=1, column=1)124 input_delay.insert(0, '50')125126 Label(root, text='请输入端口号:').grid(row=2, column=0)127 input_port = Entry(root)128 input_port.grid(row=2, column=1)129 input_port.insert(0, 'COM3')130131 Label(root, text='请输入波特率:').grid(row=3, column=0)132 input_baudrate = Entry(root)133 input_baudrate.grid(row=3, column=1)134 input_baudrate.insert(0, '9600')135136 Button(137 root, text='实时监控', command=now_draw).grid(138 row=1, column=2, columnspan=1)139 Button(140 root, text='开始画图', command=drawPic).grid(141 row=2, column=2, columnspan=1)142 Button(143 root, text='打开端口', command=serial_data).grid(144 row=3, column=2, columnspan=1)145146 # 启动事件循环147 root.mainloop()
这里倒是学习了下 Tkinter 的相关操作,还是不错的。自定义的能力更强。不过很可惜。
并不是很适合处理动态数据显示。
ORG-MODE 部分
1简单模板对应快捷输入的首字母 2 3输入 < 后面跟一个字母,然后按 TAB 键,就可以生成对应的模板。(eg: