雅特力AT-START-F423开发板

news2024/9/22 15:38:04

文章目录

    • 1、开箱
    • 2、硬件设计
    • 3、点灯初试
    • 4、gpio输入和中断
    • 5、定时器基本定时
    • 6、定时器输出PWM
    • 7、串口使用
    • 8、ADC和DAC测试
    • 9、IIC驱动OLED测试
    • 10、SPI驱动测试
    • 11、总结

1、开箱

最近官方给寄了板子,顺便测评一下吧,首先是开箱环节
在这里插入图片描述
板子是调试器+开发板的布局,接口上用了typec接口好评
在这里插入图片描述
默认的是个流水灯的效果,来看个图
请添加图片描述
现在来了解下这个板子,资料的话参考这个官网的数据吧
https://www.arterytek.com/cn/product/AT32F423.jsp#Resource
这个芯片还是不错的,主打一个国产替代
在这里插入图片描述
这个是开发板的资料,直接下载这个压缩包就能拿到开发板的相关资料了
在这里插入图片描述
下面是keil的pack包,如果用keil开发的话就下载这个包然后安装就行了
在这里插入图片描述
让人比较惊喜的是这个,这是个开发工具,大概流程有点像stm32的cube的那一套了
在这里插入图片描述
如果用官方的工具来开发的话,大概流程是这样的:
· 1、先用下面的工具生成代码
在这里插入图片描述
· 2、使用at32ide写代码
在这里插入图片描述
编译和调试也都可以走at32ide来实现
在这里插入图片描述
当然也可以用keil来弄,只要在这个里面选一下使用mdk来生成就行了
在这里插入图片描述
之后就能打开了,编译也是正常的
在这里插入图片描述
调试器用默认的这个dsp就行
在这里插入图片描述
直接下载OK
在这里插入图片描述

2、硬件设计

看一下测评的这个开发板的参数吧,这个软件还挺好用的,打开就这样了
在这里插入图片描述
这个板子主频还不错,有150mhz,比st的一些f4的板子都要好了,时钟树如下
在这里插入图片描述
下面看下硬件吧,板子是核心板加调试器的布局,调试器也是一个at32的mcu,型号如下所示:
在这里插入图片描述
然后是核心板
在这里插入图片描述
5v-3.3v的ldo电路
在这里插入图片描述
再关注一下这里的按键和led
在这里插入图片描述

3、点灯初试

这里我们先用at32 ide来尝试吧,但是我感觉这个ide不太好用,有缺点,这个我们后面再说,先配置一下led
在这里插入图片描述
设置一下这三个led即可
在这里插入图片描述
可以在工具的代码预览看到代码
在这里插入图片描述
下面使用ide来打开,这里选择导入我们刚刚生成的工程
在这里插入图片描述
选择现有项目
在这里插入图片描述
之后选定刚刚的路径即可
在这里插入图片描述
打开工程就是这样了
在这里插入图片描述
点击左上角的锤子图标编译通过
在这里插入图片描述
下载的话要配置一下先
在这里插入图片描述
跟我一样就行
在这里插入图片描述
下载软件
在这里插入图片描述
如果要debug,就点击这个虫子就行,跑起来是这个样子
在这里插入图片描述
如果要添加自己的文件,尽量用这三个
在这里插入图片描述
包含路径就是属性里面的这个
在这里插入图片描述
当然也可以用keil来开发,生成代码的时候选一下mdk就行了
在这里插入图片描述
打开项目是这样的
在这里插入图片描述
下面开始点个灯,在固件库里面找到这个函数
在这里插入图片描述
然后它本身也有个延时函数,是这个wk_system.c里面的
在这里插入图片描述
代码大概就是这样的,就是循环亮三个灯了
在这里插入图片描述
但是我觉得他这个官方的延时函数不是很好用,就模仿正点原子重新弄了一套,基于嘀嗒定时器实现的,需要的自取,代码如下:
systick.c

/*
 * systick.c
 *
 *  Created on: 2024 Aug 5
 *      Author: lx
 */


/**
  **************************************************************************
  * @file     at32f423_board.c
  * @brief    set of firmware functions to manage leds and push-button.
  *           initialize delay function.
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "systick.h"

/** @addtogroup AT32F423_board
  * @{
  */

/** @defgroup BOARD
  * @brief onboard periph driver
  * @{
  */

/* delay macros */
#define STEP_DELAY_MS                    50



/* delay variable */
static __IO uint32_t fac_us;
static __IO uint32_t fac_ms;

/**
  * @brief  initialize delay function
  * @param  none
  * @retval none
  */
void delay_init()
{
  /* configure systick */
  systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
  fac_us = system_core_clock / (1000000U);
  fac_ms = fac_us * (1000U);
}

/**
  * @brief  inserts a delay time.
  * @param  nus: specifies the delay time length, in microsecond.
  * @retval none
  */
void delay_us(uint32_t nus)
{
  uint32_t temp = 0;
  SysTick->LOAD = (uint32_t)(nus * fac_us);
  SysTick->VAL = 0x00;
  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ;
  do
  {
    temp = SysTick->CTRL;
  }while((temp & 0x01) && !(temp & (1 << 16)));

  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  SysTick->VAL = 0x00;
}

/**
  * @brief  inserts a delay time.
  * @param  nms: specifies the delay time length, in milliseconds.
  * @retval none
  */
void delay_ms(uint16_t nms)
{
  uint32_t temp = 0;
  while(nms)
  {
    if(nms > STEP_DELAY_MS)
    {
      SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
      nms -= STEP_DELAY_MS;
    }
    else
    {
      SysTick->LOAD = (uint32_t)(nms * fac_ms);
      nms = 0;
    }
    SysTick->VAL = 0x00;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    do
    {
      temp = SysTick->CTRL;
    }while((temp & 0x01) && !(temp & (1 << 16)));

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick->VAL = 0x00;
  }
}

/**
  * @brief  inserts a delay time.
  * @param  sec: specifies the delay time, in seconds.
  * @retval none
  */
void delay_sec(uint16_t sec)
{
  uint16_t index;
  for(index = 0; index < sec; index++)
  {
    delay_ms(500);
    delay_ms(500);
  }
}

/**
  * @}
  */

/**
  * @}
  */


systick.h

/*
 * systick.h
 *
 *  Created on: 2024 Aug 5
 *      Author: lx
 */

#ifndef SYSTICK_H_
#define SYSTICK_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "stdio.h"
#include "at32f423.h"


/* delay function */
void delay_init(void);
void delay_us(uint32_t nus);
void delay_ms(uint16_t nms);
void delay_sec(uint16_t sec);

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

#ifdef __cplusplus
}
#endif

#endif /* SYSTICK_H_ */

需要的话就添加如下:
在这里插入图片描述
使用逻辑分析仪测量,跟实际上的差了3ms
在这里插入图片描述

4、gpio输入和中断

上面的led算是gpio输出了,这个来看一下gpio输入吧,还是使用自家的图形化配置工具,选择pin,可以看到之前设置过的gpio
在这里插入图片描述
点开可以看到具体的io设置
在这里插入图片描述
这里我们的按键是PA0引脚,看电路默认是下拉的,按下后触发高电平
在这里插入图片描述
这里选一下下拉模式
在这里插入图片描述
保存代码后查看也能看到我们的修改
在这里插入图片描述
下面开始实现按键修改led状态,去库里面查找,应该就是这个函数了
在这里插入图片描述
简单实现一个轮询的方式,代码如下:
在这里插入图片描述
烧录后正常运行
在这里插入图片描述

下面实现一下中断触发吧,先还是在这里配置一下
在这里插入图片描述
上升沿
在这里插入图片描述
设置为下拉
在这里插入图片描述
最后开启一下中断
在这里插入图片描述
生成代码,然后打开,已经有中断的程序了
在这里插入图片描述
中断回调函数也自己生成了
在这里插入图片描述
把之前的逻辑放到这里,看下效果,也能实现按键触发中断
在这里插入图片描述
效果如下
在这里插入图片描述

5、定时器基本定时

下面实现一下定时器的基本定时功能,查看一下大概有这么多
在这里插入图片描述
数据手册中描述如下:
在这里插入图片描述
跟stm32比较相似,因此可以采用定时器6/7实现一个基本的定时器设置如下图(这样生成的时间是1ms一次的溢出)
在这里插入图片描述
其实我发现他这里还有个图,这个图就很直观了,对新手很友好
在这里插入图片描述

然后记得开中断
在这里插入图片描述
下面实现一下定时器点灯,下面的逻辑也是1s闪烁一次了
在这里插入图片描述
但是发现跑不起来,后面查了一下资料才发现原来有bug,要在这里加一行这个才行。
在这里插入图片描述
也用逻辑分析仪跑一下
在这里插入图片描述

6、定时器输出PWM

之前设置led的时候,发现这个led其实还绑定着pwm呢,例如下面的这个PD15,就绑定了TMR4的4通道,因此可以来测试一下这个定时器,这三个通道分别对应定时器4的的234通道,在下面设置一下
在这里插入图片描述
开启定时器
在这里插入图片描述
设置模式
在这里插入图片描述
使用下面的函数设置占空比
在这里插入图片描述
使用下面的函数设置占空比
在这里插入图片描述
逻辑分析仪测一下
在这里插入图片描述
在定时器的循环里面实现一下流水灯
在这里插入图片描述
效果如下:
在这里插入图片描述

7、串口使用

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
下面测试一下串口中断,在配置工具上开启这个中断
在这里插入图片描述
加入下面的回环测试程序

#define UART_BUFFER_LEN 20
uint8_t uart_buffer[UART_BUFFER_LEN] = {0};
uint8_t uart_rxindex = 0;
uint8_t uart_rxlen = 0;
uint8_t uart_txindex = 0;
uint8_t uart_txlen = 0;

void starttx()
{
    uart_txlen += uart_rxlen;
    uart_rxlen = 0;
    usart_interrupt_enable(USART1, USART_TDBE_INT, TRUE);
}

void USART1_IRQHandler(void)
{
  /* add user code begin USART1_IRQ 0 */
    if(usart_flag_get(USART1, USART_RDBF_FLAG) != RESET)
    {
        usart_flag_clear(USART1, USART_RDBF_FLAG);
        uart_buffer[uart_rxindex++] = usart_data_receive(USART1);
        if(uart_rxindex == UART_BUFFER_LEN)
            uart_rxindex = 0;
        uart_rxlen++;
    }
    if(usart_flag_get(USART1, USART_IDLEF_FLAG) != RESET || uart_rxlen == UART_BUFFER_LEN/2)
    {
        usart_flag_clear(USART1, USART_IDLEF_FLAG);
        starttx();
    }
    if(usart_flag_get(USART1, USART_TDBE_FLAG) != RESET)
    {
        usart_flag_clear(USART1, USART_TDBE_FLAG);
        if(uart_txlen > 0)
        {
            usart_data_transmit(USART1, uart_buffer[uart_txindex++]);
            if(uart_txindex == UART_BUFFER_LEN)
                uart_txindex = 0;
            uart_txlen--;
        }
        else
        {
            usart_interrupt_enable(USART1, USART_TDBE_INT, FALSE);
        }
    }
  /* add user code end USART1_IRQ 0 */
  /* add user code begin USART1_IRQ 1 */

  /* add user code end USART1_IRQ 1 */
}

接上串口,测试结果如下
在这里插入图片描述

8、ADC和DAC测试

下面开始测试adc,在图形化配置工具开启adc
在这里插入图片描述
这边的默认即可,这里我改到了12位,这样就是0-3.3v对应的0-4096的值
在这里插入图片描述
这里生成代码也要注意,开启这个才行
在这里插入图片描述
然后每次测试都加上这个
在这里插入图片描述
测试结果如下,可以看到adc正常工作
在这里插入图片描述
下面来测试使用dma的效果
在这里插入图片描述
对三个通道进行如下设置
在这里插入图片描述
定义一个数组来临时存储数据
在这里插入图片描述
根据生成代码的注释,这里是设置的地址
在这里插入图片描述
周期开启dma转换,开启中断和adc的转换
在这里插入图片描述
中断进行如下设置,就是在dma拿到数据后更新数据
在这里插入图片描述
下载测试结果如下:
在这里插入图片描述
下面测试dac,在配置工具中开启dac
在这里插入图片描述
这里直接设置默认就行
在这里插入图片描述
尝试设置一下电压
在这里插入图片描述
用万用表测量电压准确,实际上这个还有很多好玩的,可以生成噪声信号,正弦信号啥的,直接可以用,应该是sdk里面提供的,还是很舒服的。

9、IIC驱动OLED测试

开启iic,配置如下
在这里插入图片描述
这里面最坑的一点在这里,就是这个库里面没有常用的iic的函数
在这里插入图片描述
得加入这个库才行
在这里插入图片描述
这个库的函数如下,这才是我们要用的库
在这里插入图片描述

但是这个库又跟dma绑定了,所以为了防止编译错误,要开启这个才行
在这里插入图片描述
之后加入iic的驱动

#include "iic.h"

#include "i2c_application.h"

#define I2Cx_ADDRESS                     0x78

#define I2Cx_PORT                        I2C1
#define I2Cx_CLK                         CRM_I2C1_PERIPH_CLOCK
#define I2Cx_DMA                         DMA1
#define I2Cx_DMA_CLK                     CRM_DMA1_PERIPH_CLOCK

#define I2Cx_SCL_GPIO_CLK                CRM_GPIOB_PERIPH_CLOCK
#define I2Cx_SCL_GPIO_PIN                GPIO_PINS_6
#define I2Cx_SCL_GPIO_PinsSource         GPIO_PINS_SOURCE6
#define I2Cx_SCL_GPIO_PORT               GPIOB
#define I2Cx_SCL_GPIO_MUX                GPIO_MUX_4

#define I2Cx_SDA_GPIO_CLK                CRM_GPIOB_PERIPH_CLOCK
#define I2Cx_SDA_GPIO_PIN                GPIO_PINS_7
#define I2Cx_SDA_GPIO_PinsSource         GPIO_PINS_SOURCE7
#define I2Cx_SDA_GPIO_PORT               GPIOB
#define I2Cx_SDA_GPIO_MUX                GPIO_MUX_4
#define I2Cx_CLKCTRL                   0x10F03C6A   //200K

i2c_handle_type hi2cx;

/**
  * @brief  initializes peripherals used by the i2c.
  * @param  none
  * @retval none
  */
void i2c_lowlevel_init(i2c_handle_type *hi2c)
{
    gpio_init_type gpio_init_structure;

    if (hi2c->i2cx == I2Cx_PORT) {
        /* i2c periph clock enable */
        crm_periph_clock_enable(I2Cx_CLK, TRUE);
        crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
        crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
        /* gpio configuration */
        gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);
        gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);
        /* configure i2c pins: scl */
        gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
        gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
        gpio_init_structure.gpio_pull           = GPIO_PULL_UP;
        gpio_init_structure.gpio_pins           = I2Cx_SCL_GPIO_PIN;
        gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);
        /* configure i2c pins: sda */
        gpio_init_structure.gpio_pins           = I2Cx_SDA_GPIO_PIN;
        gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure);
        /* config i2c */
        i2c_init(hi2c->i2cx, 0x0F, I2Cx_CLKCTRL);
        i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2Cx_ADDRESS);
    }
}

void II2CGpioInit(void)
{
#if 0
    gpio_init_type gpio_init_struct;
    /* enable gpioc periph clock */
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    gpio_default_para_init(&gpio_init_struct);
    /* gpio output config */
    gpio_bits_write(GPIOC, IO_SCL_PIN | IO_SDA_PIN, TRUE);
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = IO_SCL_PIN | IO_SDA_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOC, &gpio_init_struct);
#else
    gpio_init_type gpio_init_structure;
    crm_periph_clock_enable(I2Cx_CLK, TRUE);
    crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
    crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
    /* gpio configuration */
    gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);
    gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);
    /* configure i2c pins: scl */
    gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
    gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_structure.gpio_pull           = GPIO_PULL_UP;
    gpio_init_structure.gpio_pins           = I2Cx_SCL_GPIO_PIN;
    gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);
    /* configure i2c pins: sda */
    gpio_init_structure.gpio_pins           = I2Cx_SDA_GPIO_PIN;
    gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure);
    hi2cx.i2cx = I2Cx_PORT;
    /* i2c config */
    i2c_config(&hi2cx);
#endif
}
/*****************************************************************************
 * @name       :void IIC_Start(void)
 * @date       :2018-09-13
 * @function   :start iic bus
 * @parameters :None
 * @retvalue   :None
******************************************************************************/
void IIC_Start(void)
{
    OLED_SCL_SET();
    OLED_SDA_SET();
    OLED_SDA_CLR();
    OLED_SCL_CLR();
}

/*****************************************************************************
 * @name       :void IIC_Stop(void)
 * @date       :2018-09-13
 * @function   :stop iic bus
 * @parameters :None
 * @retvalue   :None
******************************************************************************/
void IIC_Stop(void)
{
    OLED_SCL_SET();
    OLED_SDA_CLR();
    OLED_SDA_SET();
}

/*****************************************************************************
 * @name       :void IIC_Wait_Ack(void)
 * @date       :2018-09-13
 * @function   :wait iic ack
 * @parameters :None
 * @retvalue   :None
******************************************************************************/
void IIC_Wait_Ack(void)
{
    OLED_SCL_SET();
    OLED_SCL_CLR();
}

/*****************************************************************************
 * @name       :void Write_IIC_Byte(uint8_t IIC_Byte)
 * @date       :2018-09-13
 * @function   :Write a byte of content with iic bus
 * @parameters :IIC_Byte
 * @retvalue   :None
******************************************************************************/
void Write_IIC_Byte(uint8_t IIC_Byte)
{
    i2c_status_type i2c_status;
#if 0
    uint8_t i;
    uint8_t m, da;
    da = IIC_Byte;
    OLED_SCL_CLR();

    for (i = 0; i < 8; i++) {
        m = da;
        m = m & 0x80;

        if (m == 0x80) {
            OLED_SDA_SET();
        } else {
            OLED_SDA_CLR();
        }

        da = da << 1;
        OLED_SCL_SET();
        OLED_SCL_CLR();
    }

#else
    uint8_t buff[2] = {0};
    buff[0] = IIC_Byte;
    i2c_status = i2c_master_transmit(&hi2cx, I2Cx_ADDRESS, buff, 1, 1000);

    if (i2c_status != I2C_OK) {
        printf("erro send %d", i2c_status);
    }

#endif
}

/*****************************************************************************
 * @name       :void Write_IIC_Command(uint8_t IIC_Command)
 * @date       :2018-09-13
 * @function   :Write a byte of command to oled screen
 * @parameters :IIC_Command:command to be written
 * @retvalue   :None
******************************************************************************/
void Write_IIC_Command(uint8_t IIC_Command)
{
    i2c_status_type i2c_status;
#if 0
    IIC_Start();
    Write_IIC_Byte(IIC_SLAVE_ADDR);            //Slave address,SA0=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x00);			//write command
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Command);
    IIC_Wait_Ack();
    IIC_Stop();
#else
    uint8_t buff[2] = {0};
    buff[0] = 0x00;
    buff[1] = IIC_Command;
    i2c_status = i2c_master_transmit(&hi2cx, I2Cx_ADDRESS, buff, 2, 1000);

    if (i2c_status != I2C_OK) {
        printf("erro send %d", i2c_status);
    }

#endif
}

/*****************************************************************************
 * @name       :void Write_IIC_Data(uint8_t IIC_Data)
 * @date       :2018-09-13
 * @function   :Write a byte of data to oled screen
 * @parameters :IIC_Data:data to be written
 * @retvalue   :None
******************************************************************************/
void Write_IIC_Data(uint8_t IIC_Data)
{
    i2c_status_type i2c_status;
#if 0
    IIC_Start();
    Write_IIC_Byte(IIC_SLAVE_ADDR);			//D/C#=0; R/W#=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x40);			//write data
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Data);
    IIC_Wait_Ack();
    IIC_Stop();
#else
    uint8_t buff[2] = {0};
    buff[0] = 0x40;
    buff[1] = IIC_Data;
    i2c_status = i2c_master_transmit(&hi2cx, I2Cx_ADDRESS, buff, 2, 1000);

    if (i2c_status != I2C_OK) {
        printf("erro send %d", i2c_status);
    }

#endif
}

iic.h

#ifndef _IIC_H_
#define _IIC_H_

#include "at32f423.h"

//本测试程序使用的是软件模拟IIC接口驱动
//IIC的数据引脚定义和时钟引脚定义都可以任意修改
//修改引脚定义后,需要对应修改oled.c中OLED_Init_GPIO函数里面引脚初始化

//定义IIC从设备地址:OLED上设置的访问地址为0x78
#define IIC_SLAVE_ADDR 0x78

//--------------IIC端口操作定义---------------------

#define IO_SCL_PIN    GPIO_PINS_2
#define IO_SCL_GPIO_PORT    GPIOC
#define IO_SDA_PIN    GPIO_PINS_3
#define IO_SDA_GPIO_PORT    GPIOC

#define	OLED_SDA_SET()  	gpio_bits_write(IO_SCL_GPIO_PORT, IO_SDA_PIN, TRUE)
#define	OLED_SDA_CLR()  	gpio_bits_write(IO_SCL_GPIO_PORT, IO_SDA_PIN, FALSE)
  
#define	OLED_SCL_SET()  	gpio_bits_write(IO_SCL_GPIO_PORT, IO_SCL_PIN, TRUE)
#define	OLED_SCL_CLR()  	gpio_bits_write(IO_SCL_GPIO_PORT, IO_SCL_PIN, FALSE)


//IIC操作函数
void II2CGpioInit(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Wait_Ack(void);
void Write_IIC_Byte(uint8_t IIC_Byte);
void Write_IIC_Command(uint8_t IIC_Command);
void Write_IIC_Data(uint8_t IIC_Data);

#endif

使用下面代码测试
在这里插入图片描述
实现如下效果
在这里插入图片描述

10、SPI驱动测试

这里用一个spi的屏幕来测试spi,驱动是st7735
在这里插入图片描述
驱动代码如下



#include "lcd_init.h"
#include "systick.h"

//#define delay_ms delay_1ms

/******************************************************************
 * 函 数 名 称:LCD_GPIO_Init
 * 函 数 说 明:对LCD引脚初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:注意是使用软件SPI还是硬件SPI
******************************************************************/
void LCD_GPIO_Init(void)
{
#if 	USE_SOFTWARE
    /* 使能时钟 */
//    rcu_periph_clock_enable(RCU_LCD_CLK);
//    rcu_periph_clock_enable(RCU_LCD_MOS);
//    rcu_periph_clock_enable(RCU_LCD_CS);
//    rcu_periph_clock_enable(RCU_LCD_DC);
//    rcu_periph_clock_enable(RCU_LCD_RES);
//    rcu_periph_clock_enable(RCU_LCD_BLK);
//    
//    gpio_init(PORT_LCD_CLK, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_CLK);
//    gpio_bit_write(PORT_LCD_CLK, GPIO_LCD_CLK, SET);
//    
//    gpio_init(PORT_LCD_MOS, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_MOS);
//    gpio_bit_write(PORT_LCD_MOS, GPIO_LCD_MOS, SET);
//    
//    gpio_init(PORT_LCD_DC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_DC);
//    gpio_bit_write(PORT_LCD_DC, GPIO_LCD_DC, SET);

//    gpio_init(PORT_LCD_RES, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_RES);
//    gpio_bit_write(PORT_LCD_RES, GPIO_LCD_RES, SET);

//    gpio_init(PORT_LCD_BLK, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_BLK);
//    gpio_bit_write(PORT_LCD_BLK, GPIO_LCD_BLK, SET);

//    gpio_init(PORT_LCD_CS, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_CS);
//    gpio_bit_write(PORT_LCD_CS, GPIO_LCD_CS, SET);

#else
    spi_parameter_struct spi_init_struct;
    rcu_periph_clock_enable(RCU_LCD_CLK);
    rcu_periph_clock_enable(RCU_LCD_MOS);
    rcu_periph_clock_enable(RCU_LCD_CS);
    rcu_periph_clock_enable(RCU_LCD_DC);
    rcu_periph_clock_enable(RCU_LCD_RES);
    rcu_periph_clock_enable(RCU_LCD_BLK);
    rcu_periph_clock_enable(RCU_SPI_HARDWARE);  // 使能SPI
    rcu_periph_clock_enable(RCU_AF);
    
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);

    gpio_init(PORT_LCD_DC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_DC);
    gpio_bit_write(PORT_LCD_DC, GPIO_LCD_DC, SET);

    gpio_init(PORT_LCD_RES, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_RES);
    gpio_bit_write(PORT_LCD_RES, GPIO_LCD_RES, SET);

    gpio_init(PORT_LCD_BLK, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_BLK);
    gpio_bit_write(PORT_LCD_BLK, GPIO_LCD_BLK, SET);

    gpio_init(PORT_LCD_CS, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_LCD_CS);
    gpio_bit_write(PORT_LCD_CS, GPIO_LCD_CS, SET);

    /* 配置 SPI 参数 */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;  // 传输模式全双工
    spi_init_struct.device_mode          = SPI_MASTER;   // 配置为主机
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT; // 8位数据
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;  // 软件cs
    spi_init_struct.prescale             = SPI_PSC_32;//2分频
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(PORT_SPI, &spi_init_struct);
    /* 使能 SPI */
    spi_enable(PORT_SPI);
#endif
}



/******************************************************************
 * 函 数 名 称:LCD_Writ_Bus
 * 函 数 说 明:LCD串行数据写入函数
 * 函 数 形 参:dat  要写入的串行数据
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:注意是使用软件SPI还是硬件SPI
******************************************************************/
void LCD_Writ_Bus(u8 dat)
{
#if USE_SOFTWARE
    u8 i;
    LCD_CS_Clr();

    for (i = 0; i < 8; i++) {
        LCD_SCLK_Clr();

        if (dat & 0x80) {
            LCD_MOSI_Set();
        } else {
            LCD_MOSI_Clr();
        }

        LCD_SCLK_Set();
        dat <<= 1;
    }

    LCD_CS_Set();
#else
    LCD_CS_Clr();

    while (RESET == spi_i2s_flag_get(PORT_SPI, SPI_FLAG_TBE));

    spi_i2s_data_transmit(PORT_SPI, dat);

    while (RESET == spi_i2s_flag_get(PORT_SPI, SPI_FLAG_RBNE));

    spi_i2s_data_receive(PORT_SPI);
    LCD_CS_Set();
#endif
}


/******************************************************************
 * 函 数 名 称:LCD_WR_DATA8
 * 函 数 说 明:LCD写入8位数据
 * 函 数 形 参:dat 写入的数据
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void LCD_WR_DATA8(u8 dat)
{
    LCD_Writ_Bus(dat);
}


/******************************************************************
 * 函 数 名 称:LCD_WR_DATA
 * 函 数 说 明:LCD写入16位数据
 * 函 数 形 参:dat 写入的数据
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void LCD_WR_DATA(u16 dat)
{
    LCD_Writ_Bus(dat >> 8);
    LCD_Writ_Bus(dat);
}


/******************************************************************
 * 函 数 名 称:LCD_WR_REG
 * 函 数 说 明:LCD写入命令
 * 函 数 形 参:dat 写入的命令
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void LCD_WR_REG(u8 dat)
{
    LCD_DC_Clr();//写命令
    LCD_Writ_Bus(dat);
    LCD_DC_Set();//写数据
}

/******************************************************************
 * 函 数 名 称:LCD_Address_Set
 * 函 数 说 明:设置起始和结束地址
 * 函 数 形 参:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void LCD_Address_Set(u16 x1, u16 y1, u16 x2, u16 y2)
{
    if (USE_HORIZONTAL == 0) {
        LCD_WR_REG(0x2a);//列地址设置
        LCD_WR_DATA(x1 + 2);
        LCD_WR_DATA(x2 + 2);
        LCD_WR_REG(0x2b);//行地址设置
        LCD_WR_DATA(y1 + 1);
        LCD_WR_DATA(y2 + 1);
        LCD_WR_REG(0x2c);//储存器写
    } else if (USE_HORIZONTAL == 1) {
        LCD_WR_REG(0x2a);//列地址设置
        LCD_WR_DATA(x1 + 2);
        LCD_WR_DATA(x2 + 2);
        LCD_WR_REG(0x2b);//行地址设置
        LCD_WR_DATA(y1 + 1);
        LCD_WR_DATA(y2 + 1);
        LCD_WR_REG(0x2c);//储存器写
    } else if (USE_HORIZONTAL == 2) {
        LCD_WR_REG(0x2a);//列地址设置
        LCD_WR_DATA(x1 + 1);
        LCD_WR_DATA(x2 + 1);
        LCD_WR_REG(0x2b);//行地址设置
        LCD_WR_DATA(y1 + 2);
        LCD_WR_DATA(y2 + 2);
        LCD_WR_REG(0x2c);//储存器写
    } else {
        LCD_WR_REG(0x2a);//列地址设置
        LCD_WR_DATA(x1 + 1);
        LCD_WR_DATA(x2 + 1);
        LCD_WR_REG(0x2b);//行地址设置
        LCD_WR_DATA(y1 + 2);
        LCD_WR_DATA(y2 + 2);
        LCD_WR_REG(0x2c);//储存器写
    }
}
/******************************************************************
 * 函 数 名 称:LCD_Init
 * 函 数 说 明:LCD初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void LCD_Init(void)
{
    LCD_GPIO_Init();//初始化GPIO
    LCD_RES_Clr();//复位
    delay_ms(100);
    LCD_RES_Set();
    delay_ms(100);
    LCD_BLK_Set();//打开背光
    delay_ms(100);
    //************* Start Initial Sequence **********//
    LCD_WR_REG(0x11); //Sleep out
    delay_ms(120);              //Delay 120ms
    //------------------------------------ST7735S Frame Rate-----------------------------------------//
    LCD_WR_REG(0xB1);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_REG(0xB2);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_REG(0xB3);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x05);
    LCD_WR_DATA8(0x3C);
    LCD_WR_DATA8(0x3C);
    //------------------------------------End ST7735S Frame Rate---------------------------------//
    LCD_WR_REG(0xB4); //Dot inversion
    LCD_WR_DATA8(0x03);
    //------------------------------------ST7735S Power Sequence---------------------------------//
    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x04);
    LCD_WR_REG(0xC1);
    LCD_WR_DATA8(0XC0);
    LCD_WR_REG(0xC2);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0xC3);
    LCD_WR_DATA8(0x8D);
    LCD_WR_DATA8(0x2A);
    LCD_WR_REG(0xC4);
    LCD_WR_DATA8(0x8D);
    LCD_WR_DATA8(0xEE);
    //---------------------------------End ST7735S Power Sequence-------------------------------------//
    LCD_WR_REG(0xC5); //VCOM
    LCD_WR_DATA8(0x1A);
    LCD_WR_REG(0x36); //MX, MY, RGB mode

    if (USE_HORIZONTAL == 0) {
        LCD_WR_DATA8(0x00);
    } else if (USE_HORIZONTAL == 1) {
        LCD_WR_DATA8(0xC0);
    } else if (USE_HORIZONTAL == 2) {
        LCD_WR_DATA8(0x70);
    } else {
        LCD_WR_DATA8(0xA0);
    }

    //------------------------------------ST7735S Gamma Sequence---------------------------------//
    LCD_WR_REG(0xE0);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x22);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x0A);
    LCD_WR_DATA8(0x2E);
    LCD_WR_DATA8(0x30);
    LCD_WR_DATA8(0x25);
    LCD_WR_DATA8(0x2A);
    LCD_WR_DATA8(0x28);
    LCD_WR_DATA8(0x26);
    LCD_WR_DATA8(0x2E);
    LCD_WR_DATA8(0x3A);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x13);
    LCD_WR_REG(0xE1);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x16);
    LCD_WR_DATA8(0x06);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x2D);
    LCD_WR_DATA8(0x26);
    LCD_WR_DATA8(0x23);
    LCD_WR_DATA8(0x27);
    LCD_WR_DATA8(0x27);
    LCD_WR_DATA8(0x25);
    LCD_WR_DATA8(0x2D);
    LCD_WR_DATA8(0x3B);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x01);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x13);
    //------------------------------------End ST7735S Gamma Sequence-----------------------------//
    LCD_WR_REG(0x3A); //65k mode
    LCD_WR_DATA8(0x05);
    LCD_WR_REG(0x29); //Display on
}

lcd_init.h



#ifndef __LCD_INIT_H
#define __LCD_INIT_H

#include "at32f423.h"

#ifndef u8
#define u8 uint8_t
#endif

#ifndef u16
#define u16 uint16_t
#endif

#ifndef u32
#define u32 uint32_t
#endif

#define USE_SOFTWARE  1  //是否使用软件SPI 0使用硬件SPI  1使用软件SPI
#define USE_HORIZONTAL 1  //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏


#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160

#else
#define LCD_W 160
#define LCD_H 128
#endif


//#define TCLK 		PBout(13)  	//PB13  SCLK--
//#define TDIN 		PBout(15)  	//PB15   MOSI--
//#define DOUT 		PBin(14)   	//PB14   MISO--
//#define TCS  		PGout(6)  	//PG6  CS2--
//#define PEN  		PGin(7)    //PG7  INT--


//-----------------LCD端口移植----------------
//GND  - GND
//VCC  - 3.3V
//CLK  - PB13 SPI1_SCK
//MOS  - PB15 SPI1_MOSI
//RES  - PD0(可以接入复位)
//DC   - PC6
//BLK  - PC7- TIMER7_CH0
//MIS  - PB14 SPI1_MISO
//CS1  - PB12
//CS2  - PG6
//PEN  - PG7
//NC   - 不用接

//#define RCU_LCD_CLK     RCU_GPIOA//SCK
#define PORT_LCD_CLK    GPIOA
#define GPIO_LCD_CLK    GPIO_PINS_6

//#define RCU_LCD_MOS     RCU_GPIOA//MOSI
#define PORT_LCD_MOS    GPIOA
#define GPIO_LCD_MOS    GPIO_PINS_7

//#define RCU_LCD_CS      RCU_GPIOE//NSS
#define PORT_LCD_CS     GPIOE
#define GPIO_LCD_CS     GPIO_PINS_10

//#define RCU_LCD_DC      RCU_GPIOA //DC
#define PORT_LCD_DC     GPIOE
#define GPIO_LCD_DC     GPIO_PINS_11

//#define RCU_LCD_RES     RCU_GPIOA//RES
#define PORT_LCD_RES    GPIOE
#define GPIO_LCD_RES    GPIO_PINS_12

//#define RCU_LCD_BLK     RCU_GPIOA//BLK
#define PORT_LCD_BLK    GPIOE
#define GPIO_LCD_BLK    GPIO_PINS_13

/******** 硬件SPI修改此次 ********/
//#define RCU_SPI_HARDWARE RCU_SPI0
//#define PORT_SPI         SPI0
//#define LINE_AF_SPI      GPIO_PINS_5


//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() gpio_bits_write(PORT_LCD_CLK, GPIO_LCD_CLK, FALSE)//SCL=SCLK
#define LCD_SCLK_Set() gpio_bits_write(PORT_LCD_CLK, GPIO_LCD_CLK, TRUE)

#define LCD_MOSI_Clr() gpio_bits_write(PORT_LCD_MOS, GPIO_LCD_MOS, FALSE)//SDA=MOSI
#define LCD_MOSI_Set() gpio_bits_write(PORT_LCD_MOS, GPIO_LCD_MOS, TRUE)

#define LCD_RES_Clr()  gpio_bits_write(PORT_LCD_RES, GPIO_LCD_RES, FALSE)//RES
#define LCD_RES_Set()  gpio_bits_write(PORT_LCD_RES, GPIO_LCD_RES, TRUE)

#define LCD_DC_Clr()   gpio_bits_write(PORT_LCD_DC, GPIO_LCD_DC, FALSE)//DC
#define LCD_DC_Set()   gpio_bits_write(PORT_LCD_DC, GPIO_LCD_DC, TRUE)

#define LCD_CS_Clr()   gpio_bits_write(PORT_LCD_CS, GPIO_LCD_CS, FALSE)//CS
#define LCD_CS_Set()   gpio_bits_write(PORT_LCD_CS, GPIO_LCD_CS, TRUE)

#define LCD_BLK_Clr()  gpio_bits_write(PORT_LCD_BLK, GPIO_LCD_BLK, FALSE)//BLK
#define LCD_BLK_Set()  gpio_bits_write(PORT_LCD_BLK, GPIO_LCD_BLK, TRUE)


void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1, u16 y1, u16 x2, u16 y2); //设置坐标函数
void LCD_Init(void);//LCD初始化



#endif

使用如下代码
在这里插入图片描述
测试效果如下

在这里插入图片描述

11、总结

首先这个板子性能很强,有stm32F4的水平了,这个没啥问题,然后生态也不错,这个是我觉得很好的地方,这决定了我在一些地方会用这个板子。
但是这个图形化配置工具还是有点bug,比如上次选了勾选全部库,第二次打开就不是了,然后就是iic的bug,希望后续能继续优化,然后希望这个图形化配置工具能融合到ide里面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

栈与队列,优先队列与双端队列(C++)

在C语言阶段&#xff0c;我们学过两种数据结构&#xff0c;栈与队列&#xff0c;一种是先进后出&#xff0c;一种是先进先出。 在C阶段&#xff0c;我们有新容器来方便快捷的使用栈和队列而不需要我们手动来编写 即stack与queue 我们直接来看对应接口 stack 同时放上对应的…

9.标准化与软件知识产权基础知识

大纲 标准的分类 标准的编号 保护期限 知识产权的确定 侵权判断 补充 真题 1

全国大学生数据建模比赛——深度学习

全国大学生数学建模比赛中&#xff0c;深度学习可以成为解决复杂问题的有力手段。 一、深度学习的优势在比赛中的体现 强大的模式识别能力&#xff1a;深度学习模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;和循环神经网络&#xff08;RNN&#xff09;&#xff0…

Linux 系统进程管理实战

今天给伙伴们分享一下Linux 系统进程管理&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路上得到支持和共同进步…

系统分析师6:计算机网络

文章目录 1 OSI/RM七层模型2 TCP/IP协议族2.1 常见TCP/IP协议基础2.2 DNS 3 IP地址4 网络规划与设计4.1 网络规划与设计的阶段4.2 层次化网络设计 5 综合布线6 网络存储技术-Raid7 网络接入技术 1 OSI/RM七层模型 集线器多个端口属于同一个冲突域&#xff1b; 交换机多个端口属…

nexus 清理 docker 镜像

下载配置 nexus-cli 看网上文档都用如下地址&#xff0c;但现在已经不能下载&#xff1a; wget https://s3.eu-west-2.amazonaws.com/nexus-cli/1.0.0-beta/linux/nexus-cli chmod x nexus-cli 在 github 上下载&#xff1a; wget https://github.com/heyonggs/nexus-cli/r…

【202408最新】Anaconda+VSCode+CUDA+Pytorch安装配置保姆级教程

最近新换了电脑&#xff0c;又开始从头配置代码环境&#xff0c;到处看教程真的一个头两个大&#xff0c;干脆自己整理了一下&#xff0c;方便以后一站式重装。也提供给大家参考。 1.Anaconda下载安装 Anaconda和Python是替代品&#xff08;也不是&#xff09;&#xff0c;下…

uniapp引入最新版Animate.css及使用示例

亲测可用,不好用请移至评论区揍我 动画库官网:https://animate.style/ cdn地址:https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css(截至目前最新版为:v4.1.1) 1. 将css下载后导入项目static目录中 2. 重要!修改下载的css文件内容 文件内容如…

Audi TT MK1保险丝盒布局说明书

Audi TT MK1保险丝盒布局说明书 保险丝序号额定最大电流(A)对应功能描述110加热式洗涤器喷嘴、加热式后视镜210转向灯35车牌灯45通用电气&#xff0c;导航57.5停车辅助65中控锁系统710倒车灯85电话95防抱死制动系统/ESP1015发动机正时:汽油机115仪表盘、换档锁、自动&#xff0…

了解内网穿透以及简单应用

因特网概述 节点&#xff08;Node&#xff09;&#xff1a;网络中的节点可以是计算机&#xff08;笔记本电脑、台式电脑&#xff0c;服务器等&#xff09;、网络互联设备&#xff08;集线器、交换机&#xff0c;路由器等&#xff09;、其他具有联网功能的设备 &#xff08;网络…

TCP 之 三次握手 (面经计网篇)

这是tcp 简历连接的三次握手方式 , 其中的特殊符号 , 我解释下 , SYN 是 同步的这个单词(synchronization), ACK 是回执,承认的单词(acknowledgement), SYN-ACK 服务器收到SYN报文后&#xff0c;回复一个带有SYN和ACK标志的报文段&#xff0c;这表示服务器已经收到了客户端的SY…

【C++ Primer Plus习题】8.7

问题: 解答: #include <iostream>using namespace std;template <typename T> T SumArray(T arr[], int n) {T sum arr[0] - arr[0];for (int i 0; i < n; i){sum arr[i];}return sum; }template <typename T> T SumArray(T *arr[], int n) {T sum *…

sqli-libs第四关详解

首先判断是数字型注入还是字符型注入 正常显示&#xff0c;说明是字符型注入&#xff0c;那么尝试单引号闭合 还是正常显示&#xff0c;尝试双引号闭合 有报错信息&#xff0c;含有括号&#xff0c;这时就应该想到&#xff0c;sql代码是("$id")这样写的了。直接采取闭…

强化学习——马尔可夫决策过程的理解

目录 一、马尔可夫决策过程1.策略2.状态价值函数3.动作价值函数4.贝尔曼期望方程 参考文献 一、马尔可夫决策过程 马尔可夫决策过程&#xff08;MDP&#xff09;是马尔可夫奖励过程&#xff08;MRP&#xff09;的扩展&#xff0c;它引入了“动作”这一外界的影响因素&#xff0…

翻译新选择!除了在线翻译百度,还有这三款宝藏工具等你发现

咱们来聊聊现在世界变成一个“大家庭”的事儿。现在&#xff0c;世界各地的人们交流越来越多&#xff0c;语言不通不再是障碍了&#xff01;翻译工具就像超级护照&#xff0c;帮我们轻松跨越语言障碍。说到翻译&#xff0c;百度翻译真的很有名&#xff0c;速度快&#xff0c;翻…

JAVA中的线程池说明一

系列文章 JAVA中的线程池说明一 JAVA中的线程池说明二 目录 1.为什么需要线程池? 2.什么是线程池? 3.标准库中的线程池 4.实现自定义线程池 1.为什么需要线程池? 线程的存在意义在于解决并发编程中进程开销过大的问题&#xff0c;因此引入了线程&#xff0c;也被称为…

【Hot100】LeetCode—74. 搜索二维矩阵

原题链接&#xff1a; 74. 搜索二维矩阵 1- 思路 二分 ① 实现一个二分函数② 对每行数组进行二分 2- 实现 ⭐74. 搜索二维矩阵——题解思路 class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int[] m:matrix){if(binarySearch(m,target)){re…

【知识图谱】3、Python操作图数据库neo4j示例

今天突然想起上次知识图谱系列埋了一个坑&#xff08;【知识图谱】1、Neo4j环境搭建入门指南:从零开始玩转图数据库&#xff09;&#xff0c;说后续写一篇关于Python操作neo4j的示例。趁着周六有充足时间&#xff0c;这里写个demo补上。 本文demo还是以面试的求职者、岗位要求…

浅谈-Unity内存管理

灵魂拷问-什么是内存 物理内存虚拟内存内存寻址方位 物理内存 下面是一张i7的处理器的芯片细节图&#xff0c;在整个板载面积上我们可以很明显的看到Shared L3 Cache占用了最大面积。为什么&#xff1f;因为硬件产商为了让我们忽略掉CPU访问内存是一个非常慢速的过程&#x…

Nginx: TCP建立连接的优化和启用Fast Open功能

TCP 建立连接优化 在三次握手中&#xff0c;相关TCP的内核参数可优化这一过程 net.ipv4.tcp_syn_retries 6net.ipv4.tcp_synack_retries 5net.ipv4.tcp_syncookies 0net.ipv4.tcp_max_syn_backlognet.core.somaxconnnet.core.netdev_max_backlog 1 &#xff09; net.ipv4…