【单片机入门】(二)应用层软件开发的单片机学习之路—–点灯大师

引言

在上一博客中,我们正式开始了单片机的学习之路,讲了单片机的概念,以及我们使用的ESP32系列的单片机的IO引脚,讲了什么是GPIO,以及相关的总线通讯概念(UART,IIC,SPI),脉冲调制概念(PWM),以及信号数字互转的(ADC和DAC),板子自带的一些功能,在今天的博客中,我会带你们正式进入控制硬件的第一课;

不管是什么单片机,入门第一课都是点亮LED灯,俗称”点灯大师”,哈哈,我们的第一课也是点灯,那我在群里,没有让大家去购买LED,是因为我们实际上可以使用代码去控制ESP板子上面的其中一个LED灯管,当电源接通后会有一个电源灯,红色的灯亮起,电源正常,同时还有一个灯为蓝色的,默认为不显示的,接下来我们便让ESP32开发板的另外一个LED灯进行闪烁。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

点灯

void setup() {

  // put your setup code here, to run once:
 pinMode(2,OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(2, LOW);    // sets the LED off
  delay(1000);
}         

先上代码,如上所示,即可点亮板子的另一个蓝色的灯,先讲一下代码,上面的setup,一个单片机通电,只会运行一次,即每通电一次,运行一次,下面的loop是循环的一个代码,通电期间,一直循环,先运行setup,在运行loop,上面的setup顾名思义,是用来对单片机做一些配置,上面的配置就是将第二个引脚设置为输出,即单片机向引脚2输出,输出高低电平,用来点亮LED灯,在ESP32中,蓝色灯的引脚为2,所以在此处我们设置引脚2为输出模式,

第二个loop循环代码,第一行调用了一个digitalWrite的方法,这个方法是给我们指定的引脚写入高低电平,以此来给某个引脚开关通电,断电,第一个参数为要写入的引脚的pin值,即引脚值,第二个参数为需要写入的值,HIGH,LOW这两个为高低电平,HIGH通电,LOW断电,第二行代码,则是一个延迟函数,里面的值是毫秒值,1000,即代表暂停一秒

下面的gif展示了我们这次的一个运行结果,可以看到蓝色灯在不停的进行闪烁。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

代码编译和烧录

在我们代码写完成之后,我们需要编译,然后在烧写到单片机里面去,那每次写完之后呢,在编辑器左上角有一个对号的按钮,我们点击这个按钮之后,ide会开始编译我们的代码,在编译之后,我们需要将代码烧录到单片机内部,点击对号旁边的右箭头按钮,代码开始烧录,等待下方出现Connecting的时候,我们要让单片机进入下载模式,单片机上面有两个按钮,电源灯上面有一个按钮,同横着水平旁边还有一个按钮,当出现了Connecting的时候需要去按住下方箭头所指的那个按钮不松手,则会写入程序。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

Arduino

我们的开发IDE为Arduino,我之前配过vsc使用纯c语言去进行开发ESP32单片机,后面使用了Arduino,因为这个相比于纯c来说更简单一些,更适合入门,但是对于C开发,原理也是一样的,无非就是写法上纯在差异。

在程序运行都是不停的在进行循环代码,但是方法上一个是main方法,一个是loop其他的就是语法的区别了,Arduino是基于c和c++进行封装的,里面的封装更趋近于高级语言,这里展示一下Arduino的一些方法或者常量,数据类型等。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

C语言

而对于c语言来说,有的基础不好,或者没有深入使用过c语言的来讲是有一些难度的,我在这里贴一下我之前写的一个红外线控制智能小车的代码,此处使用的是esp32原生的c文件来进行开发,其复杂程度和Arduino相比还是略现复杂。

/* brushed dc motor control example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.

*/

/*
 * This example will show you how to use MCPWM module to control brushed dc motor.

 * This code is tested with L298 motor driver.

 * User may need to make changes according to the motor driver they use.

 */

#include
#include "sdkconfig.h"
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "driver/rmt.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#include "IR_Rev.h"
// const static char *TAG = "IR_Rre Demo";

#define RECV_PIN 23  // 一体化红外接收头GPIO
uint8_t command = 0; // 接收到的ENC红外指令
int direction = 0;
float currentspeed = 0;
int currentcolor = 2;
#define GPIO_PWM0A_OUT 15 // Set GPIO 15 as PWM0A
#define GPIO_PWM0B_OUT 16 // Set GPIO 16 as PWM0B
#define GPIO_PWM1A_OUT 17
#define GPIO_PWM1B_OUT 18
#define GPIO_PWM2A_OUT 12 // Set GPIO 15 as PWM0A
#define GPIO_PWM2B_OUT 14 // Set GPIO 16 as PWM0B
#define GPIO_PWM3A_OUT 25
#define GPIO_PWM3B_OUT 26
#define RED 2
#define GREEN 4
#define BLUE 5
#define INFARE 21
static void mcpwm_example_gpio_initialize(void)
{
    printf("initializing mcpwm gpio...\n");
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_PWM1A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, GPIO_PWM1B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM0A, GPIO_PWM2A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM0B, GPIO_PWM2B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1A, GPIO_PWM3A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1B, GPIO_PWM3B_OUT);
}
// forwards he forward 替换实现顺时针吹风和逆时针吹风
/**
 * @brief motor moves in forward direction, with duty cycle = duty %
 */
static void brushed_motor_forward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A);
    mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle);
    mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); // call this each time, if operator was previously in low/high state
}
static void brushed_motor_forwards(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    ESP_ERROR_CHECK(mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B));
    ESP_ERROR_CHECK(mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle));
    ESP_ERROR_CHECK(mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0)); // call this each time, if operator was previously in low/high state
}
// forwards he forward 替换实现顺时针吹风和逆时针吹风
/**
 * @brief motor moves in forward direction, with duty cycle = duty %
 */
static void brushed_motor_backward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B);
    mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle);
    mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0); // call this each time, if operator was previously in low/high state
}
static void brushed_motor_backwards(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    ESP_ERROR_CHECK(mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A));
    ESP_ERROR_CHECK(mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle));
    ESP_ERROR_CHECK(mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0)); // call this each time, if operator was previously in low/high state
}

/**
 * @brief motor stop
 */
static void brushed_motor_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A);
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B);
}

static void setspeed(uint8_t command)
{
    if ((uint8_t)command == 22)
    {
        printf("%d\n", 22);
        currentspeed = 10;
    }
    else if ((uint8_t)command == 12)
    {
        printf("%d\n", 12);
        currentspeed = 20;
    }
    else if ((uint8_t)command == 24)
    {
        printf("%d\n", 24);
        currentspeed = 30;
    }
    else if ((uint8_t)command == 94)
    {
        printf("%d\n", 94);
        currentspeed = 40;
    }
    else if ((uint8_t)command == 8)
    {
        printf("%d\n", 8);
        currentspeed = 50;
    }
    else if ((uint8_t)command == 28)
    {
        printf("%d\n", 28);
        currentspeed = 60;
    }
    else if ((uint8_t)command == 90)
    {
        printf("%d\n", 90);
        currentspeed = 70;
    }
    else if ((uint8_t)command == 66)
    {
        printf("%d\n", 66);
        currentspeed = 80;
    }
    else if ((uint8_t)command == 82)
    {
        printf("%d\n", 82);
        currentspeed = 90;
    }
    else if ((uint8_t)command == 74)
    {
        printf("%d\n", 74);
        currentspeed = 100;
    }
}
static void head(float speed)
{
    brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, speed);
    brushed_motor_forwards(MCPWM_UNIT_0, MCPWM_TIMER_1, speed);
    brushed_motor_forward(MCPWM_UNIT_1, MCPWM_TIMER_0, speed);
    brushed_motor_forwards(MCPWM_UNIT_1, MCPWM_TIMER_1, speed);
}
static void last(float speed)
{
    brushed_motor_backward(MCPWM_UNIT_0, MCPWM_TIMER_0, speed);
    brushed_motor_backwards(MCPWM_UNIT_0, MCPWM_TIMER_1, speed);
    brushed_motor_backward(MCPWM_UNIT_1, MCPWM_TIMER_0, speed);
    brushed_motor_backwards(MCPWM_UNIT_1, MCPWM_TIMER_1, speed);
}
static void left(float speed)
{
    mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A);
    mcpwm_set_signal_low(MCPWM_UNIT_1, MCPWM_TIMER_0, MCPWM_OPR_B);
}
static void right(float speed)
{
    mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B);
    mcpwm_set_signal_low(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A);
}
/**
 * @brief Configure MCPWM module for brushed dc motor
 */
static void mcpwm_example_brushed_motor_control(void *arg)
{
    // 1. mcpwm gpio initialization
    mcpwm_example_gpio_initialize();

    // 2. initial mcpwm configuration
    printf("Configuring Initial Parameters of mcpwm...\n");
    mcpwm_config_t pwm_config;
    pwm_config.frequency = 1000; // frequency = 500Hz,
    pwm_config.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_config.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_config.counter_mode = MCPWM_UP_COUNTER;
    pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config)); // Configure PWM0A & PWM0B with above settings
    mcpwm_config_t pwm_configs;
    pwm_configs.frequency = 1000; // frequency = 500Hz,
    pwm_configs.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configs.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configs.counter_mode = MCPWM_UP_COUNTER;
    pwm_configs.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_configs)); // Configure PWM0A & PWM0B with above settings

    mcpwm_config_t pwm_configA;
    pwm_configA.frequency = 1000; // frequency = 500Hz,
    pwm_configA.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configA.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configA.counter_mode = MCPWM_UP_COUNTER;
    pwm_configA.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_0, &pwm_configA)); // Configure PWM0A & PWM0B with above settings
    mcpwm_config_t pwm_configAs;
    pwm_configAs.frequency = 1000; // frequency = 500Hz,
    pwm_configAs.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configAs.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configAs.counter_mode = MCPWM_UP_COUNTER;
    pwm_configAs.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_0, &pwm_configAs)); // Configure PWM0A & PWM0B with above settings */ */
    while (1)
    {
        command = IRrecvReadIR();

        printf("IR Command is %02X\n", command);
        printf("IR 111 is %d\n", (uint8_t)command);
        if ((uint8_t)command == 69)
        {
            brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0);
            brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_1);
            brushed_motor_stop(MCPWM_UNIT_1, MCPWM_TIMER_0);
            brushed_motor_stop(MCPWM_UNIT_1, MCPWM_TIMER_1);
        }
        else if ((uint8_t)command == 64)
        {
            direction = 64;
            head(currentspeed);
        }
        else if ((uint8_t)command == 25)
        {
            direction = 25;
            last(currentspeed);
        }
        else if ((uint8_t)command == 7)
        {
            printf("IR 32 is %d\n", (uint8_t)command);
            left(currentspeed);
        }
        else if ((uint8_t)command == 9)
        {
            printf("IR 23 is %d\n", (uint8_t)command);
            right(currentspeed);
        }
        else
        {
            printf(" %d\n", direction);
            setspeed(command);
            if (direction == 64)
            {
                head(currentspeed);
            }
            else if (direction == 25)
            {
                last(currentspeed);
            }
        }
    }
}
static void openlight(void *arg)
{
    gpio_set_level(INFARE, 1);
    while (1)
    {

        gpio_set_level(currentcolor, 1);
        vTaskDelay(200 / portTICK_PERIOD_MS);
        gpio_set_level(currentcolor, 0);
        if(currentcolor==2)
        {
            currentcolor=4;
        }
        else if (currentcolor==4)
        {
            currentcolor=5;
        }
        else if (currentcolor==5)
        {
            currentcolor=2;
        }
    }

}
void app_main(void)
{
    IRrecvInit(RECV_PIN, 3);
    gpio_set_direction(INFARE, GPIO_MODE_OUTPUT);
    gpio_set_direction(RED, GPIO_MODE_OUTPUT);
    gpio_set_direction(GREEN, GPIO_MODE_OUTPUT);
    gpio_set_direction(BLUE, GPIO_MODE_OUTPUT);
    xTaskCreate(mcpwm_example_brushed_motor_control, "mcpwm_examlpe_brushed_motor_control", 4096, NULL, 5, NULL);
    xTaskCreate(openlight, "openlight", 4096, NULL, 5, NULL);
}

而令我最喜欢Arduino的一点是,我们需要使用一些第三方库的时候,这里的扩展相比VSC更容易找一些,C的话在插件市场极大可能找不到,需要在网上自己搜索,找到c语言写好的文件,然后include进来再去使用,找的话有点难度,对于红外线来讲,上次我在网上找就找了挺久的一段时间。而在Arduino我只需在管理库界面搜索我想要的库或者关键字都可以找到,emmm,我觉得就像nuget一样简单,哈哈,所以我更喜欢用这个一点。

在这里,我们就可以根据关键字,类型去搜索我们想要的第三方库,很方便,同时有的第三方库也是有例子可以直接使用,总体来说,作为简单入门,Arduino还是很不错的一个选择。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

结语

好啦,今天的点灯第一课就到这里啦,如果又不懂的可以随时问我,可以加这个群一起来学习单片机,后面还会开stm32系列的课程,IDE的话可以看上一篇博客中的下载地址是有百度网盘的地址,同时群文件也有,有需要的可以下载啦,我们系列教程会出到可以自己做一个智能小车为止。

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

Original: https://www.cnblogs.com/1996-Chinese-Chen/p/16814553.html
Author: 四处观察
Title: 【单片机入门】(二)应用层软件开发的单片机学习之路—–点灯大师

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/800403/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 当 chatGPT 被职场 PUA ,笑麻了!

    大家最近是不是被 chatGPT 刷屏了?简单来说,chatGPT 是一个智能聊天引擎。 那 chatGPT 和小爱同学、 siri 有什么区别呢? 如果体验过的朋友,能感受到区别…

    Python 2023年11月4日
    030
  • Python索引index常用的8种操作

    原始数据为 csv 文件。 data ”’ date,temperature,humidity 07/01/21,95,50 07/02/21,94,55 07/03/21,94…

    Python 2023年8月17日
    039
  • python的Django项目中常见命令以及常错点(Linux环境下)

    ### 回答1: Python_是一种非 _常_流行的编程语言,它可以支持各种类型的应用程序开发,并且有着优秀的编码效率和代码可读性,因此被广泛应用。而 _Django_作为 _P…

    Python 2023年8月5日
    057
  • Python学习34:自我复习:Pytest和Unitest

    Python主流框架 – Unittest unittest是Python标准库中自带的一款单元测试框架,支持自动化测试,测试用例的初始化和关闭,测试用例的聚合等功能 …

    Python 2023年9月14日
    035
  • NumPy数组属性

    本节介绍 Numpy 数组的常用属性。 ndarray.shape shape 属性的返回值一个由数组维度构成的元组,比如 2 行 3 列的二维数组可以表示为(2,3),该属性可以…

    Python 2023年8月26日
    036
  • python-flask-mysql完整web项目

    公众号:不会写代码的阿P 项目源码在文章最下方—> 项目结构: 1.数据库连接池 通过pip插入数据驱动依赖 pip install flask-sqlalche…

    Python 2023年8月12日
    051
  • PyTorch进阶学习笔记[长期更新]

    啊哦~你想找的内容离你而去了哦 内容不存在,可能为如下原因导致: ① 内容还在审核中 ② 内容以前存在,但是由于不符合新 的规定而被删除 ③ 内容地址错误 ④ 作者删除了内容。 可…

    Python 2023年8月29日
    037
  • 集合方法及运算

    1.增加元素:方法add()。 set_val = {‘hello’,123,(1,2,3)}set_val.add(‘world’)print(set_val)​输出结果:{‘h…

    Python 2023年6月3日
    061
  • Python笔记(3)——列表二:操作列表(Python编程:从入门到实践)

    1. 遍历整个列表:使用for循环 执行第1行代码定义列表colors,执行第2行代码;for语句末尾的冒号告诉Python,下一行是循环的第一行。进入 第一次循环: 第2行代码获…

    Python 2023年10月29日
    043
  • Cenots7 离线安装部署PostgreSQL

    1 PostgreSQL源码包下载并复制 1.1 PostgreSQL源码包下载: 访问PostgreSQL官网 选择所需版本进行下载,本次下载安装版本为v14.5 1.2 复制源…

    Python 2023年10月17日
    037
  • HTML怎么设置图片大小

    html插入图片有两种方式:一种是通过标签插入的正常的图片,另一种是通过css样式插入的背景图片 1、首先你是通过第二种方式插入的是背景图片,直接用width和height只能控制…

    Python 2023年6月9日
    086
  • day08_python中的属性(01)

    day08_python中的属性(01) 原创 wx5e6caa8b9792d2022-08-01 17:05:33博主文章分类:Python自动化开发 ©著作权 文章标签 pyt…

    Python 2023年5月24日
    057
  • Keras入门(七)使用Flask+Keras-bert构建模型预测服务

    在文章NLP(三十四)使用keras-bert实现序列标注任务中,我们介绍了如何使用keras-bert模块,利用BERT中文预训练模型来实现序列标注任务的模型训练、模型评估和模型…

    Python 2023年8月15日
    046
  • MachineLearning入门—第6章—TensorFlow的低阶API简介

    TensorFlow的低阶API主要包括张量操作,计算图和⾃动微分。如果把模型⽐作⼀个房⼦,那么低阶API就是【模型之砖】。在低阶API层次上,可以把TensorFlow当做⼀个增…

    Python 2023年8月27日
    055
  • Pointnet/Pointnet++学习

    一、点云的应用二、点云的表述三、Pointnet四、Pointnet++ Pointnet++概述虽然这篇文章叫PointNet++,但和PointNet相比还是有很大的改进。文章…

    Python 2023年8月2日
    044
  • pytest文档81 – 如何管理Captured logging日志

    前言 pytest 自动捕获级别为 WARNING 或以上的日志消息,并以与捕获的 stdout 和 stderr 相同的方式在每个失败测试的各自部分中显示它们。 日志显示 当输入…

    Python 2023年9月11日
    050
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球