用python写一个发送hex到单片机boot的简单小程序(YFW)

通过串口烧入hex到pic单片机(pic已经运行boot程序)

down_hex.py 源码

#coding:utf-8
import serial
import pic_hex_pars
import time
from threading import Timer
#串口定时接收
class PicSerial():
    def __init__(self):
        self.t = Timer(0.02, self.func)
        self.t.start()
        self.ser=serial.Serial("com1", 57600, timeout=0.5)
        self.rx_data=[0,0,0,0,0,0,0,0]

    def func(self):

        try:
            num = self.ser.inWaiting()
        except:
            t.ser.close()
            return None
        if num > 0:
            self.rx_data = self.ser.read(num)
            num = len(self.rx_data)
            # print(num)
            # print(self.rx_data[0],self.rx_data[1])
            # print("com2接收:",rx_data.decode('iso-8859-1'))
            # print(self.rx_data)
        self.t.cancel()
        self.t = Timer(0.02, self.func)
        self.t.start()
        
PROGRAM_DEVICE_CMD=[0xD0,0XF2,0X05,0X00,0X20,0X00,0X00,0X36,0X37,0X38]  ### 烧写程序命令,PROGRAM_DEVICE_CMD【00 20 00 00 表示起始地址0x00002000(左边为低字节)】
hex_data,start_addr=pic_hex_pars.hex_pars()  #读取代码数据
print("编程地址:", hex(start_addr))
print("转换后的代码行数:",len(hex_data))

# 从hex中获取代码起始地址
addr_l=start_addr%256
addr_h=start_addr//256
PROGRAM_DEVICE_CMD[3] = addr_l 
PROGRAM_DEVICE_CMD[4] = addr_h

pic_ser = PicSerial() #打开串口
pic_ser.ser.write(PROGRAM_DEVICE_CMD) #开始烧写程序命令,指定了烧写起始地址
time.sleep(1)#等待命令完成
for i in range(0, len(hex_data)):
    data=bytearray.fromhex(hex_data[i])
    print("第",i,"帧下载中:", hex_data[i],"\n\r")
    pic_ser.ser.write(data)  # 写8字节程序数据到单片机
    #等待一帧数据下载完成
    while  pic_ser.rx_data[0]!=54 or pic_ser.rx_data[1]!=54:
        0
    # print(t.rx_data[0], t.rx_data[1], t.rx_data[2])
    print("第",i,"帧下载完成!块填充计数监控值:", pic_ser.rx_data[2],"\n\r") #打印提示信息
    pic_ser.rx_data =[0,0,0,0,0,0,0,0]

print("hex发送完成")

pic_hex_pars.py 源码

#coding:utf-8
import binascii
import os
import linecache
#检查校应码
def calc_checksum( data):
    checksum = 0
    result=0
    # print("校应数据长度:",len(data))
    for i in range(0, len(data),2):
        checksum = ((int(data[i:i +2], 16))+checksum )
    # print(checksum)
    result=(256-checksum)&0xff
    # print(result)
    return result

def hex_pars(path="./led.hex"):
    DOWN_DATA_CMD = [0xD0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF]  ###写ROM指令:【D0 F1 FF FF FF FF FF FF FF FF】, FF FF FF FF FF FF FF FF 表示要写入的数据数据(左边为低
    hex_result = [] #存储解析结果
    start_addr=0
    linenum=0
    data_line_num=0
    file_path = path
    fptr = open(file_path, "r")
    while True:
        line = fptr.readline().upper()  ###读取一行文本,并且小写字母转大写字母
        line = line.strip()  ##删除头尾空格和换行符
        if len(line) != 0:
                 # print(line)
                 length = int(line[1:3], 16)
                 addr =  int(line[3:7], 16)
                 rtype = int(line[7:9], 16)
                 checksum = calc_checksum(line[1:-2])
                 # print("校应和:", hex(checksum))
                 if checksum == int(line[-2:], 16):
                     # print("校验正确",linenum)
                     # 校验正确。
                     if rtype == 0x00 and addr > 0 and length > 0:
                         data_line_num+=1
                         #取得hex代码的起始地址
                         if  data_line_num ==1 :
                               start_addr=addr
                         data_len = length
                         send_times = (length // 8) if length % 8 == 0 else (length // 8 + 1)
                         # print("大循环次数", send_times)
                         #8字节为单位遍历一行数据
                         for j in range(0, send_times):
                             #遍历16进制字符串转字节数组,提取一行中的8字节数据
                             for i in range(0, 8):
                                 if data_len != 0:
                                     data_len = data_len - 1
                                     # print(i)
                                     DOWN_DATA_CMD[2 + i] = int(line[(9 + i * 2 + j * 16):(11 + i * 2 + j * 16)], 16)
                                     # 提取数据到二维数组
                             # 追加(一个编程指令)到二维数组
                             hex_result.append(bytearray(DOWN_DATA_CMD).hex())
                             # print("提取8字节数据:", bytearray(DOWN_DATA_CMD).hex())
                     else:
                         print("数据不符合要求,行号:", linenum)
                 else:
                     print("校应失败,行号:", linenum)
        else:
            block_num=len(hex_result)//8   # 完整块数量(64字节等于一个块)
            debris_num=len(hex_result)%8    # 剩余行数(一个行等于8字节,需要补齐到64字节)
            # print("hex转换完成,完整块数量:",block_num,"剩余行数:",debris_num)
            lack_line_number=8-debris_num  #计算需要补齐多少行
            #补齐缺少行
            for j in range(0, lack_line_number):
                hex_result.append(bytearray([0xD0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).hex())
            for j in range(0, len(hex_result)):
                print(hex_result[j])
            print("转换后的代码行数:", len(hex_result))
            break
        linenum += 1
    return hex_result,start_addr

运行示例(如下图):
在这里插入图片描述

一帧发送8字节数据。PIC_BOOT 需要接收64字节才写入ROM。

led.hex文件内容

:040000002CEF10F0E1
:10200000000E026E000E016E400E015C1F0E0258A3
:10201000D8B01200000E046E000E036E045007E1EB
:10202000280E035CD8B003D0034A042AF7D7014A2C
:10203000022AEAD7000E826E000E8B6E000E946E9E
:10204000010E8B6E00EC10F0000E8B6E00EC10F0A9
:0E205000F7D700F000F000F000011AEF10F0DA
:020000040020DA
:08000000FFFFFFFFFFFFFFFF00
:020000040030CA
:0E00000011087F7CFF0F81FF0FC00FE00F4043
:00000001FF

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yfw&武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值