【雅特力AT32学习】从0开始的国产芯片学习 | AT32F413 | F425 | STM32 | 总结笔记

雅特力AT32芯片学习总结笔记

一、芯片介绍

1、基础概念

  • 内核:32 位的ARM®Cortex®-M4FCPU(学习用到的芯片是 AT32F425R8T7) > 内存(64 K),SRAM(20 K),工作频率最高 96 M
  • 特性汇总

所有GPIO口可以映像到16个外部中断(EXINT)

2、配置相关

 (一)ISP(在线编程)利用芯片特定通信接口(如 UART、SPI 等),通过简单连接在芯片特定模式下更新固件,常用于成本控制严、功能简单设备 ### (二)ICP(在线电路编程)通过专门接口(如 JTAG、SWD)连接,除编程外还具强大调试功能,应用于对芯片性能和调试要求高的领域如工业自动化、通信等。

  • 工程例程打开流程
//1、user里面

- at32f425_clock.c时钟配置文件,设置了默认的时钟频率及时钟路径

- at32f425_int.c中断文件,默认编写了部分内核中断函数的代码流程

- main.c模板工程的主代码文件

//2、bsp里面

- at32f425_board.c板级配置文件,设置了AT-START上的按键和LED等常用硬件配置

//3、firmware里面

- firmware下的at32f425_xx.c是各片上外设的驱动文件

//4、cmsis里面

- system_at32f425.c系统初始化文件

- startup_at32f425.s启动文件

//5、readme里面

- readme.txt工程的说明文件

  • 简单工程实例(需要移植文件如下) > firmware 文件中移植了所有外设,其他文件按需要再进行移植

  • 宏定义相关
AT32F425R8T7,USE_STDPERIPH_DRIVER,AT_START_F425_V1

3、知识补充

  • 注意二进制左高右低
  • Hex 文件在 keil 中要配置 output 才会生成

二、格式基础

1、基础代码

  • 输入输出,也就是读写

gpio_input_data_bit_read(GPIOA,GPIO_PINS_0)

gpio_bits_write(GPIOC,GPIO_PINS_3,flag);

//看原理图,引脚平时处于低电平,按键按下为高(故为下拉) 
void at32_button_init(void) {
    gpio_init_type gpio_init_struct; //使能PA0对应时钟 
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK,TRUE); //设置为默认值 
    gpio_default_para_init(&gpio_init_struct); //配置按键 
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;     
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; //设置为输入模式         
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_0; //设置为下拉 
    gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; 
    gpio_init(GPIOA,&gpio_init_struct); 

}
  • 中断初始化
```c fold title:中断初始化

//中断初始化

void button_exint_init(void)

{

//外部中断结构体初始化

exint_init_type exint_init_struct;

//GPIOA外设时钟

crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

//配置外部时钟

crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);

//配置外部中断线(部分产品为GPIO),这里是GPIOA_PIN0

scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE0);



//外部中断结构体使用默认值

exint_default_para_init(&exint_init_struct);

//中断源使能

exint_init_struct.line_enable = TRUE;

//外部中断线模式为中断模式(不是事件模式)

exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;

//中断源选择

exint_init_struct.line_select = EXINT_LINE_0;

//中断事件

exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;

//中断初始化

exint_init(&exint_init_struct);



nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); //配置中断优先级分组

//注意,这里是抢占优先级4位,表示有16种不同的抢占优先级(0-15)

nvic_irq_enable(EXINT1_0_IRQn, 1, 0); //中断服务函数使能

}
  • 中断服务函数举例
```c fold title:中断服务函数
//中断服务函数 
void EXINT1_0_IRQHandler(void) 
{
 if(exint_flag_get(EXINT_LINE_0)!=RESET) 
    { //等待松手 
        while(gpio_input_data_bit_read(GPIOA,GPIO_PINS_0)!=1);
         flag=(confirm_state)!flag; gpio_bits_write(GPIOC,GPIO_PINS_3,flag);
         //清空中断标志位
         exint_flag_clear(EXINT_LINE_0);
 } 
}
  • led 初始化

    ```c fold title:led初始化
    
    void at32_led_init(void)
    
    {
    
    //定义一个结构体
    
    gpio_init_type gpio_init_struct;
    
    /* 使能对应的外设时钟,这里是LED时钟 clock */
    
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    
    /* 设置为默认值 */
    
    gpio_default_para_init(&gpio_init_struct);
    
    /* 配置相关 */
    
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    
    gpio_init_struct.gpio_pins = GPIO_PINS_3;
    
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    
    gpio_init(GPIOC, &gpio_init_struct);
    
    }

串口配置相关,写在 com.c 文件里(第二种方法 keil注意勾选这个)

```c fold title:串口配置相关 
//方式一:printf重定向 
//重定向C库函数printf到DEBUG_USARTx
 int fputc(int ch,FILE *f) {
 //等待发送缓冲区空闲 
    while(usart_flag_get(USART1,USART_TDBE_FLAG)==RESET);
     usart_data_transmit(USART1,ch); return ch; }
//方式二:串口输出相关配置 
#if (__ARMCC_VERSION > 6000000) __asm (“.global __use_no_semihosting);
 void _sys_exit(int x) 
{ 
    x = x;
 } 
/* __use_no_semihosting was requested, but _ttywrch was */
 void _ttywrch(int ch) {
     ch = ch; 
} FILE __stdout;
 #else
 #ifdef __CC_ARM #pragma import(__use_no_semihosting) struct __FILE 
{
 int handle; 
};
FILE __stdout; 
void _sys_exit(int x) 
{
     x = x;
} 
/* __use_no_semihosting was requested, but _ttywrch was */ 
void _ttywrch(int ch) { 
ch = ch; 
} 
#endif
 #endif

#if defined (GNUC) && !defined (clang) 
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) 
#else #define PUTCHAR_PROTOTYPE 
int fputc(int ch, FILE *f) 
#endif

/** * @brief retargets the c library printf function to the usart. * @param none * @retval none */
 PUTCHAR_PROTOTYPE { 
while(usart_flag_get(USART1, USART_TDBE_FLAG) == RESET);
 usart_data_transmit(USART1, (uint16_t)ch); 
while(usart_flag_get(USART1, USART_TDC_FLAG) == RESET);
 return ch; 
}

#if (defined (GNUC) && !defined (clang)) || (defined (ICCARM)) 
#if defined (GNUC) && !defined (clang) int _write(int fd, char *pbuffer, int size) 
#elif defined ( ICCARM ) 
#pragma module_name = “?__write” int __write(int fd, char pbuffer, int size) 
#endif { for(int i = 0; i < size; i ++) {
 while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET); usart_data_transmit(PRINT_UART, (uint16_t)(pbuffer++));
 while(usart_flag_get(PRINT_UART, USART_TDC_FLAG) == RESET); 
}
return size; 
} 
#endif
  • 串口初始化(这里 PA9 为 TX,PA10 为 RX)
```c fold title:串口初始化

//串口初始化

void uart_print_init(uint32_t baudrate)

{

gpio_init_type gpio_init_struct;

//使能外设时钟

crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);

crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

gpio_default_para_init(&gpio_init_struct);



//配置串口1 tx引脚

//这里TX PA9,RX PA10

gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;

gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;

gpio_init_struct.gpio_mode = GPIO_MODE_MUX; //这个模式只能设置一个,这里是引脚复用功能

gpio_init_struct.gpio_pins = GPIO_PINS_9 | GPIO_PINS_10;

gpio_init_struct.gpio_pull = GPIO_PULL_NONE;

gpio_init(GPIOA, &gpio_init_struct);



//配置串口1 rx引脚

//gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; //注意模式不同,接收模式

//前面设定了PA9的GPIO属性,并没有将PA9引脚的功能设置为串口1的TX功能

gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE9, GPIO_MUX_1); // 将 PA9 设置为 USART1_TX

gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE10, GPIO_MUX_1); // 将 PA10 设置为 USART1_RX



//配置串口1 波特率,数据位数,停止位位数

usart_init(USART1, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);

//配置校验位

usart_parity_selection_config(USART1,USART_PARITY_NONE);

usart_transmitter_enable(USART1, TRUE);

usart_receiver_enable(USART1,TRUE);

usart_enable(USART1, TRUE); //串口使能

}

(一)串口发送验证

while(USART1->sts_bit.tdbe==0);

(二)串口接收验证

c fold title:
串口接收相关 
while(USART1->sts_bit.rdbf==0);
 //接收函数举例 while(1) { 
while(USART1->sts_bit.rdbf==0);
 rx_buf = USART1->dt; if(rx_buf=='1'){ 
gpio_bits_write(GPIOC,GPIO_PINS_3,TRUE); 
}else if(rx_buf=='2'){
 gpio_bits_write(GPIOC,GPIO_PINS_3,FALSE); 
}
 }

(三)串口中断

``c fold title:串口中断相关配置 //中断配置相关 nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); 
nvic_irq_enable(USART1_IRQn,0,0); //使能中断 usart_interrupt_enable(USART1,USART_RDBF_INT,TRUE);

//中断服务函数 void USART1_IRQHandler(void) { while(usart_flag_get(USART1,USART_RDBF_FLAG)==RESET); 
rx_buf = usart_data_receive(USART1);
 if(rx_buf==‘1’){ gpio_bits_write(GPIOC,GPIO_PINS_3,TRUE);
 }else if(rx_buf==‘2’){ gpio_bits_write(GPIOC,GPIO_PINS_3,FALSE); 
} }

三、错误相关

1、GNU 扩展格式重复定义

  • 把这个勾去掉就行了

四、定时器

1、TMR 相关

  • AT32F425 最多1个高级定时器、7个通用定时器和2个基本定时器,以及1个系统滴答定时器
  • 基本定时器 TMR 6,7

3、通用定时器 TMR 2,3,13,14,15,16,17

4、高级定时器 TMR 1

五、DMA

1、配置相关

  • usart 初始化中加入
```c

//DMA发送使能

usart_dma_transmitter_enable(USART1,TRUE);

//DMA接收使能

usart_dma_receiver_enable(USART1,TRUE);

dma 初始化 ### 
(一)详细配置 
```c fold title:dma轮询 uint8_t tx_buf[] = “Hello World”; #define COUNTOF(a) (sizeof(a) / sizeof(*(a)))
//注意部分配置写在串口初始化里 //发送通道1,接收通道2 void Driver_dma_init(void) { dma_init_type dma_init_struct; /使能DMA外设时钟/ crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); /* DMA1通道1模式配置/ dma_reset(DMA1_CHANNEL1); dma_reset(DMA1_CHANNEL2); dma_default_para_init(&dma_init_struct); 
/容量配置/ dma_init_struct.buffer_size =COUNTOF(tx_buf)-1; 
/方向:由内存到外设/ dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL; 
/内存地址*/ dma_init_struct.memory_base_addr = (uint32_t)tx_buf; 
dma_init_struct.memory_data_width = DMA_ME
MORY_DATA_WIDTH_BYTE; dma_init_struct.memory_inc_enable = TRUE; 
dma_init_struct.peripheral_base_addr = (uint32_t)&(USART1->dt); 
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; 
dma_init_struct.peripheral_inc_enable = FALSE; dma_init_struct.priority = DMA_PRIORITY_MEDIUM; 
dma_init_struct.loop_mode_enable = FALSE; 
dma_init(DMA1_CHANNEL1, &dma_init_struct); 
dma_init(DMA1_CHANNEL2, &dma_init_struct);

/DMA1弹性配置/ dma_flexible_config(DMA1,FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_RX); 
dma_flexible_config(DMA1,FLEX_CHANNEL2, DMA_FLEXIBLE_UART1_TX);

/DMA1通道1中断使能/ dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); 
dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); 
/中断的初始化/ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); 
nvic_irq_enable(DMA1_Channel1_IRQn, 1, 0); 
nvic_irq_enable(DMA1_Channel3_2_IRQn, 0, 0); 
/DMA1通道1关闭,通道2打开/

dma_channel_enable(DMA1_CHANNEL1, FALSE); 
dma_channel_enable(DMA1_CHANNEL2, TRUE); }

(二)基本配置

```c fold title:dma基本配置

__IO uint16_t adc1_ordinary_valuetab[10][3] = {0};

__IO uint16_t dma_trans_complete_flag = 0;



void Driver_dma_init(void)

{

dma_init_type dma_init_struct;

/*使能DMA外设时钟*/

crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

/* DMA1通道1模式配置*/

/*dma中断分组*/

nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);

dma_reset(DMA1_CHANNEL1);

dma_default_para_init(&dma_init_struct);

/*长度设置为30*/

dma_init_struct.buffer_size = 30;

/*方向设置为外设到内存*/

dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;

/*设置内存地址*/

dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab;

/*设置字节宽度为16bit,因为adc是12bit的*/

dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;

/*开启内存增量模式*/

dma_init_struct.memory_inc_enable = TRUE;

/*设置外设地址*/

dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);

/*字节宽度同上*/

dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;

/*关闭增量模式*/

dma_init_struct.peripheral_inc_enable = FALSE;

/*dma仲裁优先级最高*/

dma_init_struct.priority = DMA_PRIORITY_HIGH;

/*循环模式关闭*/

dma_init_struct.loop_mode_enable = FALSE;

/*初始化*/

dma_init(DMA1_CHANNEL1, &dma_init_struct);

/*dma中断开启*/

dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);

/*通道1使能*/

dma_channel_enable(DMA1_CHANNEL1, TRUE);

}
  • 两个中断服务函数:发送通道与接收通道
c fold title:两个中断服务函数 
confirm_state flag = TRUE; 
void DMA1_Channel1_IRQHandler(void) { if(dma_flag_get(DMA1_FDT1_FLAG)) { dma_flag_clear(DMA1_FDT1_FLAG); flag=(confirm_state)!flag; 
gpio_bits_write(GPIOC,GPIO_PINS_3,flag); 
/关闭DMA通道/ dma_channel_enable(DMA1_CHANNEL1, FALSE);
 /重写装载/ DMA1_CHANNEL1->dtcnt =COUNTOF(tx_buf)-1; 
/开启DMA传输/ dma_channel_enable(DMA1_CHANNEL2, TRUE); 
} 
}

void DMA1_Channel3_2_IRQHandler(void) { 
if(dma_flag_get(DMA1_FDT2_FLAG)) { 
dma_flag_clear(DMA1_FDT2_FLAG); 
flag=(confirm_state)!flag; 
gpio_bits_write(GPIOD,GPIO_PINS_3,flag); 
/关闭DMA通道/ dma_channel_enable(DMA1_CHANNEL2, FALSE);

/重写装载/ DMA1_CHANNEL2->dtcnt =COUNTOF(tx_buf)-1;
 /开启DMA传输/ dma_channel_enable(DMA1_CHANNEL2, TRUE);
 if(tx_buf[0]==‘H’&&tx_buf[1]==‘e’)

dma_channel_enable(DMA1_CHANNEL1, TRUE);
 } 
} 

五、ADC

1、ADC 原理

  • 测得电压参考电压,常规转换和注入通道的转换

六、SPI

  • 后面代码过多就没上传了哈哈,可以私信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值