又是一篇踩坑记

加入了iGEM硬件组的学习, 现在上手的是51单片机. 怎么说呢, mac在这些方面真的是狗屎.

(但是明明我以前看的时候, 网上的所有教程里面的电脑都是mac, 但是现在一回过神来, 到网上找资料的时候, 全部都是windows. 真是让人摸不着头脑. )

(踩了很久的坑, 就当我为什么这么久没有更新吧… 虽然但是, 其实其他的文章我也有修补的. )

前言

我的电脑是macbook air m1, 所以以前就遭了很多罪. 参见我的第一篇博客: The First Draft!.

这里写上一些之前没提到的配置:

  • 首先是homebrew的安装, 可以说这个东西就像是linux里面的 apt-get之类的东西. 好用的很.
    要安装的话就可以参见官网
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    

    (这里有一个坑就是github的网络常常抽风. 不过神奇的是, 我用校园网竟然可以”流畅”访问. 虽然这个”流畅”是相对我用热点的访问禁止而言的… 我的错? )

  • 然后是本来我以为很强大的VSCode的滑铁卢, 可以支持一个叫PlatformIO的插件, 兼容几乎所有的单片机. – 假的, 这个更坑的样子. (其实还是我的问题)
    不知道为什么, 可能是因为STC的芯片的支持问题, 在我inclue头文件的时候, 竟然, 完全没得用!!!!!!!
    好的, 我知道原因, 是要我去自己把头文件放进去吧, 行, 但是放进去了之后又会报错 (因为编译器和提供的代码适用的语法还是有一点不同), 我…???????
    总之, 我打算返璞归真地来了.
    我就用vim, 哼.

开始配置环境

因为漂亮的环境没得用, 所以我只好用丑陋一点的命令行了.

sdcc

首先是一个编译器的安装:

brew install sdcc

轻松. 就是时间久一点, 因为我不会把homebrew的源改成国内的.

(所谓编译器, 个人理解就是一个可以把我写的垃圾代码变成机器可以直接理解的东西. 类似于gcc吧? )

(并且据说这个编译器功能还很强, 不过我不是很了解就是了. )

这里要注意一下, 就是这个编译器的有一点点的语法是和网上的部分不一样. 就是:

  MAC SDCC WINDOWS KEIL C
头文件 8051.h/8052.h reg51.h/reg52.h
IO端口 P2_0 P2^0
IO口定义 #define LED P2_0 sbit LED = P2^0
中断函数 void INT0_ISR() __interrupt 0 void INT0_ISR() interrupt 0

(摘自别人的博客, 要注意的是他/她后面的下载器部分不值得借鉴, 因为驱动没必要. )

stcgal

然后是一个下载器的安装, 选择的是stcgal. (看这个网页, 据说这个下载器高级一点. )

pip3 install stcgal

(实际上驱动没必要, 因为我装了也没法识别. )

(下载器就好像是一个把我们的代码拷贝到单片机里面的东西. )

动一动试试

vim led.c

只能说我太年轻, 以为代码复制过来就可以用了. 实际上, 要理解代码是什么. 然后才可以用.

vim写一段代码, 放在一个地方. (建议单独存放, 以免到时候太乱. )

#include <8052.h>

#define LED1 P2_7
#define LED2 P2_6

void main()
{
	while(1)
	{
		LED1 = 0;
		LED2 = 0;
	}
}

这里点了两盏灯, 这两个灯对应的引脚分别是P27, P26, (怎么知道的? 看一个叫做电路原理图的东西就好. )

电路原理图

代码的大概意思就是将LED1LED2这两个关键词用头文件里面定义过的 P2_7, P2_6代替.

(原则上说这两个就是register吧? 也就是引脚?)

可以发现, 当这两个引脚电位被拉低的时候, 对应的灯就会亮.

sdcc -mmcs51 led.c

然后用sdccled.c编译了.

sdcc -mmcs51 led.c

这个时候完美的情况是什么都不会显示, 然后就结束了, 然后ls一下就会看到一堆的输出文件, 虽然应该只要一个就好, 其他的日后再说.

ls /dev/tty.*

把机器和电脑连接上, 再用这行命令显示一下电脑上挂着的设备:

ls /dev/tty.*

(这个时候真的不知道该不该夸苹果, 外接设备少得可怜, 一下子就可以看到我挂载的机器了…)

在我这里, 名字叫/dev/tty.usbserial-1110.

stcgal -P stc89 -p /dev/tty.usbserial-1110 led.ihx

这时候下载就好了.

stcgal -P stc89 -p /dev/tty.usbserial-1110 led.ihx

-P stc89告诉程序用的是stc89的板子, -p /dev/tty.usbserial-1110告诉程序下载到哪里, led.ihx就是之前编译出来的一大堆文件中的一个.

然后运行后就会弹出:

Waiting for MCU, please cycle power:

这个时候把板子上的电源按钮按下再松开就好(类似于重启? ) (我的板子上的标识是POWER1)

Waiting for MCU, please cycle power: done
Target model:
  Name: STC89C52RC/LE52R
  Magic: F002
  Code flash: 8.0 KB
  EEPROM flash: 6.0 KB
Target frequency: 11.088 MHz
Target BSL version: 6.6C
Target options:
  cpu_6t_enabled=False
  bsl_pindetect_enabled=False
  eeprom_erase_enabled=False
  clock_gain=high
  ale_enabled=True
  xram_enabled=True
  watchdog_por_enabled=False
Loading flash: 108 bytes (Intel HEX)
Switching to 19200 baud: checking setting testing done
Erasing 2 blocks: done
Writing flash: 640 Bytes [00:00, 2113.34 Bytes/s]                               
Setting options: done
Disconnected!

万事大吉!!!

我现在感觉我会了一点了

甚至觉得也不过如此, 我可以开始起飞了.

实际情况: 只会点个灯…

QAQ

2021.12.12 - 关于串口通信

啊, 现在学了一些串口通信的知识, 所以在这里补充一下.

没有意义的原理介绍

虽然不能这样说, 但是实际上我真的不是很会这个原理.

大概是这样的吧, 就是两台机器之间要如何传递信息, 我们首先就要有一个信号传输的通道, 在这里就是数据线连接. 然后就是要有一套大家都认可的通信标准, 可以想象成要对上行话, 所以就是这么样子.

(具体实现的话, 以后再钻研. )

代码实现

怎么说呢, 从抄代码开始吧.

#include <8052.h>

// 定义一个类似于全局变量的receive变量, 
// 用来电脑通过串口发送给单片机的数据
unsigned char receive;

// serial_initialize函数是用于初始化
// 输入的参数baud表示波特率(9600)
void serial_initialize(unsigned int baud)
{
  TMOD |= 0x20;            // 计数器工作方式为2
  SCON =  0x50;            // 工作方式为1
  PCON =  0x80;            // 波特率加倍
  TH1  =  baud;            // 初始的值设置
  TL1  =  baud;
  ES   =  1;               // 打开接受中断
  TR1  =  1;               // 打开计数器
}

void serial_receive_and_respond() __interrput 4
{
  unsigned int rec_data;

  RI       = 0;            // 清除接受中断标志位
  rec_data = SBUF;         // (局部)储存接受的数据
  receive  = rec_data;     // 存储数据
  SBUF     = rec_data;     // 将接收到的数据放回发送寄存器
  while(!TI);              // 等待发送完成
  TI = 0;                  // 清除发送完成标志位
}

void main()
{
  serial_initialize(0xfa); // 初始化, 波特率为9600
  // codes...
}

大意应该就是每次有信息发送过来就开启中断, 然后在单片机里面处理相应的信息就好了.

mac的坑

又到了这个万年坑了.

在windows上有很多的工具以及参考资料, 但是在mac上嘛, 很少, 所以我只好去找linux类的工具了.

我用的串口通信工具是minicom, 安装的方法是:

brew install minicom

安装完了以后先看一下自己的单片机接在哪里:

ls /dev/tty.*

然后我的设备在电脑上的挂载的名字叫 tty.usbserial-1110(虽然我觉得名字完全不重要, 因为会变. ) 然后就是要进入minicom的设置里面, 告诉程序要在哪里去接受信息, 去用怎么样的波特率:

minicom -s

settings

serial-port

然后在A处修改地址, 在E处修改波特率. baud

最后要注意, 为了让电脑可以输入, 要在F的硬件输入流那里选择No.

(建议保存设置, 然后选择Exit退出设置, 进入连接. )

(还有一个坑, 在mac里面Meta键对应的是esc. )

(要退出的话要按esc-X, 暴力退出的话, 会出错. )