本文主要是介绍雅特力AT-START-F423开发板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 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 //200Ki2c_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 0gpio_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);
#elsegpio_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 0uint8_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();}#elseuint8_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 0IIC_Start();Write_IIC_Byte(IIC_SLAVE_ADDR); //Slave address,SA0=0IIC_Wait_Ack();Write_IIC_Byte(0x00); //write commandIIC_Wait_Ack();Write_IIC_Byte(IIC_Command);IIC_Wait_Ack();IIC_Stop();
#elseuint8_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 0IIC_Start();Write_IIC_Byte(IIC_SLAVE_ADDR); //D/C#=0; R/W#=0IIC_Wait_Ack();Write_IIC_Byte(0x40); //write dataIIC_Wait_Ack();Write_IIC_Byte(IIC_Data);IIC_Wait_Ack();IIC_Stop();
#elseuint8_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);#elsespi_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); // 使能SPIrcu_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; // 软件csspi_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_SOFTWAREu8 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();
#elseLCD_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();//初始化GPIOLCD_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 outdelay_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 inversionLCD_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); //VCOMLCD_WR_DATA8(0x1A);LCD_WR_REG(0x36); //MX, MY, RGB modeif (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 modeLCD_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里面。
这篇关于雅特力AT-START-F423开发板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!