王嘉辉 发表于 2024-10-8 00:24

【嘉楠科技 CanMV K230测评】基础外设学习二——PWM、UART、Thread、WDT、File

<p><strong>PWM</strong></p>

<p>PWM称为脉冲宽度调制,用于产生一个特定的脉冲信号,当然这个信号的频率(周期)以及占空比都可以进行灵活的设定。PWM被广泛的应用在风扇调速、舵机控制、电机控制等等中。在其他的单片机中,PWM的产生通常都需要搭配定时器进行使用,通过定时器产生一定频率(周期)的中断,并在计数到达一定的数量后,进行电平的反转,从而实现PWM信号的产生。但是在K230中的PWM产生非常的方便,仅需要几个函数就可以实现PWM的快速生成。</p>

<p>PWM也位于machine模块下,因此在使用PWM的时候,要先从machine中进行引用。</p>

<p>通过pwm = machine.PWM(channel, freq, duty, enable=False)进行PWM的函数构建,其中参数channel用于选择PWM的通道,K230提供了6个PWM通道,因此可选的范围为0-5,在这块开发板上,仅有四个通道被引出,可选的范围为0-3。参数freq用于配置PWM的频率,对应的单位为Hz。参数duty用于配置PWM的占空比,取值范围为0-100,默认值为50。enable用于配置PWM输出是否使能,默认为false即不使能状态。</p>

<p>当然PWM的频率和占空比都可以进行单独的配置,通过调用函数pwm.freq()和pwm.duty()。</p>

<p>在不使用PWM的时候,可以调用pwn.deinit()函数,将PWM功能注销掉。</p>

<p>下面进行PWM代码的演示,产生变换的PWM波形以及控制无源蜂鸣器产生不同声调的声音。</p>

<pre>
<code class="language-python">from machine import Pin, PWM
from machine import FPIOA
import time

fpioa = FPIOA()
fpioa.set_function(42,FPIOA.PWM0)

Beep = PWM(0,200, 50, enable=True)

Beep.freq(200)
time.sleep(1)

Beep.freq(400)
time.sleep(1)

Beep.freq(600)
time.sleep(1)

Beep.freq(800)
time.sleep(1)

Beep.freq(1000)
time.sleep(1)

Beep.enable(False)</code></pre>

<p>首先引入了PWM、Pin和FPIOA模块,然后先构建了FPIOA的函数,并将42号引脚配置为PWM0的功能。</p>

<p>然后构建了PWM的函数,命名为Beep,同时进行了初始化配置,配置为通道0,周期为200Hz,占空比为50,并进行使能。</p>

<p>在下面,进行频率的变换,依次变换为200、400、600、800、1000,每次变换完后进行一秒的延时,用于观察。</p>

<p>最终的演示结果如下所示。</p>

<p>a3e5afb6f2e5982ca25185c54fd09f19</p>

<p>下面进行PWM第二个功能代码的演示,用于控制180&deg;舵机,进行不同角度的变化。</p>

<p>舵机的工作原理:舵机的工作需要一个周期为20ms的脉冲信号,占空比的范围为2.5-12.5,所对应的时间为0.5ms-2.5ms,对应的角度为0-180或者-90~90。</p>

<pre>
<code class="language-python">from machine import Pin, PWM
from machine import FPIOA
import time

fpioa = FPIOA()
fpioa.set_function(42,FPIOA.PWM0)

Motor = PWM(0,50, 3, enable=True)

Motor.duty(5)
time.sleep(1)

Motor.duty(7)
time.sleep(1)

Motor.duty(9)
time.sleep(1)

Motor.duty(11)
time.sleep(1)

Motor.duty(4)
time.sleep(1)

Motor.enable(False)
</code></pre>

<p>首先引入了PWM、Pin和FPIOA模块,然后先构建了FPIOA的函数,并将42号引脚配置为PWM0的功能。</p>

<p>然后构建了PWM的函数,命名为Motor,同时进行了初始化配置,配置为通道0,周期为50Hz(周期为20ms),占空比为3,并进行使能。</p>

<p>在下面,进行频率的变换,依次变换为5、7、9、11、4,每次变换完后进行一秒的延时,用于观察。</p>

<p>最终的演示结果如下所示。</p>

<p>bde1059cc6423ef282f04ca32c7eccc5<br />
<strong>UART</strong></p>

<p>串口是最常用的串行总线,具有全双工、异步的特性。被广泛的应用在无线透传模块以及工控相关的产品上。和其他开发板的通信,往往也是使用串口进行数据的收发。</p>

<p>K230内部有5个UART硬件模块,其中UART0被小核终端占用,UART3被大核终端占用。剩余的UART1、UART2、UART4可以被连接使用,但是在这块开发板上引出了UART1、UART2。</p>

<p>UART也位于machine模块下,因此在使用UART的时候,要先从machine中进行引用。</p>

<p>machine.UART(id, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)函数用来构建函数。id为串口号,可以用的范围是UART.UART1和UART.UART2;baudrate为波特率,常用的数值为115200、9600等,使用串口通信时,首先要保证两个设备的串口波特率保持一致。bits为数据位,一般为8位,默认也为8位。parity为校验位,可以选择的有偶校验、奇校验和无校验,默认是无校验;stop为停止位设定,可以选的范围是1、1.5、2,默认为1。</p>

<p>K230使用串口与外面的设备进行通信时,配置完成后要进行数据的收发。</p>

<p>发送数据的函数为UART.write(buf),其中buf为要发送的数据。</p>

<p>接收数据的函数为UART.read(num),其中num为要接收的数据的位数。UART.readline(num)为接收整行的数据,其中num为读取的行数。</p>

<p>在不使用串口后可以使用UART.deinit()函数,将串口注销掉。</p>

<p>下面使用USB转TTL模块,将K230与电脑使用串口进行通信。</p>

<p>硬件接线方式。</p>

<div style="text-align: center;"></div>

<p>软件代码展示。</p>

<pre>
<code class="language-python">from machine import UART
from machine import FPIOA
import time

fpioa = FPIOA()

fpioa.set_function(11,FPIOA.UART2_TXD)
fpioa.set_function(12,FPIOA.UART2_RXD)

uart = UART(UART.UART2,115200)

uart.write('Hello EEWORLD')

while True:
    text = uart.read(128)
    if text != b'':
      print(text)
   
    time.sleep(0.1)
</code></pre>

<p>首先引入UART和FPIOA的模块。</p>

<p>构建一个FPIOA的函数,并将11和12两个引脚设置为串口2的TXD和RXD工作模式。构建一个UART函数,并将这个串口配置为串口2通道,波特率配置为115200。</p>

<p>使用串口写入函数,发送Hello EEWORLD字符串。</p>

<p>在循环中,接收串口接收的数据到text变量中,判断变量内容,如果不是b&#39;&#39;,则打印text内容。产生100ms的延时,避免满跑。</p>

<p>串口收发数据效果展示。在串口调试助手上,选择对应的串口号和波特率以及相应的设置,打开串口后,并运行程序,可以收到由K230发送的字符串。在数据发送编辑栏里发送数据,可以在IDE的串行终端中收到电脑通过串口发送给K230的123字符串。</p>

<div style="text-align: center;"></div>

<div style="text-align: center;"></div>

<p><strong>Thread线程</strong></p>

<p>单片机运行程序的方式是顺序运行,即代码从上至下依次进行程序的运行。但是为了实现程序的更快和更加实时,出现l实时操作系统这一概念,即RTOS。在MicroPython中有一个类似的概念,称之为线程,thread。</p>

<p>在MicroPython中对于线程的描述可以参考官方文档。<a href="https://docs.python.org/3.5/library/_thread.html#module-thread" target="_blank">17.9. _thread &mdash; Low-level threading API</a></p>

<p>使用线程最简单的方式就是通过调用_thread.start_new_thread(<em>function</em>, <em>args</em>[, <em>kwargs</em>])函数,新创建一个线程,便会开始自动运行。其中的参数function代表的是在这个线程中要被调用的函数。这个函数在线程创建函数之前,且其要完成一定的工作。参数args则是传入该函数的一些参数,这个参数的传入方式为元组。</p>

<p>使用多线程打印多条信息。代码演示。</p>

<pre>
<code class="language-python">import _thread
import time

def func(name):
    while True:
      print("hello {}".format(name))
      time.sleep(1)

_thread.start_new_thread(func,("1",))
_thread.start_new_thread(func,("2",))

while True:

    time.sleep(0.01)
</code></pre>

<p>首先引入thread模块。</p>

<p>定义一个要在多线程中运行函数,func,所执行的任务是打印一条信息,传入的参数为name。</p>

<p>在下面开启两个线程,并传入不同的参数。</p>

<p>在循环中写入一小段延时,避免单片机满跑。</p>

<p>下面进行效果延时。可以看到串行终端中不断打印定义的func函数中的数据。</p>

<div style="text-align: center;"></div>

<p><strong>WDT</strong></p>

<p>看门狗是单片机用来防止软件程序跑飞,从而出现问题的一种内部机制。其本质可以看作是一个定时器,当开启看门狗后,定时器开始运行,在定时器到达设定的重启时间之前要进行喂狗(即重置一下定时器),若超过设定的时间没有进行喂狗,就会通过软件复位的方式,将程序进行复位,从而避免了程序跑飞出现的问题。</p>

<p>在K230单片机中也有WDT模块。在使用的时候,需要先引用WDT模块,然后构建一个WDT函数,使用函数wdt = WDT(id, timeout),并在构建函数的时候配置好看门狗的编号以及超时的时间,这里的时间单位是s。喂狗的方式是调用feed函数,wdt.feed()就可以实现喂狗。</p>

<p>下面就用代码演示一下看门狗的配置和喂狗的操作。</p>

<pre>
<code class="language-python">from machine import WDT
import time

wdt = WDT(1,3)

for i in range(3):

    time.sleep(1)
    print(i)

    wdt.feed()

while True:

    time.sleep(0.01)
</code></pre>

<p>首先引入WDT模块。构建一个WDT的函数,并设置超时时间为3s。</p>

<p>执行一个循环函数,循环的次数为3次,在每一次循环的时候进行1s的延时,打印当前的循环次数,并进行一次喂狗。完成3次喂狗后,就会跳出循环,在循环外没有喂狗的操作。因此进入死循环3s后,就会自动复位,此时的开发板就会和电脑断开连接并重新连接。</p>

<p>演示视频如下。</p>

<p>9d1a36b483c17b0d20bf71cea5edcb76<br />
<strong>File</strong></p>

<p>在其他的单片机中我们要是想断电后保存一些数据的话,通常会使用EEPROM或者Flash进行数据的存储。在K230中自带一个文件系统,因此我们直接使用K230的文件系统就可以实现数据的存储和获取。</p>

<p>K230进行文件操作的方式和Python的文件操作方式是一样的。K230的文件路径为/sdcard,所创建的文件,直接存储在这个路径下即可。</p>

<p>代码展示。</p>

<pre>
<code class="language-python">f = open('/sdcard/1.txt', 'w')
f.write('EEWORLD')
f.close()

f = open('/sdcard/1.txt', 'r')
text = f.read()
print(text)
f.close()
</code></pre>

<p>构建文件函数f,并打开以写的方式,如果没有就会自动新建。使用write函数进行数据的写入。然后关闭文件。</p>

<p>打开文件以读的方式,使用read函数将数据读出并存储在text变量中,打印text,关闭文件。</p>

<p>效果演示。</p>

<p>a96345351865543210e461fa0b9b7077<br />
&nbsp;</p>

zxcvbnm751120 发表于 2024-10-8 09:21

页: [1]
查看完整版本: 【嘉楠科技 CanMV K230测评】基础外设学习二——PWM、UART、Thread、WDT、File