五、Base Timer的使用: 六、gpTimer的使用: 1、用于简单定时 2、用于pwm输出 3、输出反向PWM(带死区) 4、输出任意波形 5、用于输入捕获 七、Uart的使用 八、IIC的使用 九、CAN的使用
五、Base Timer的使用:AG32中包含2个Base Timer:分别对应TIMER0和TIMER1。 这两个timer中,每个又有两组寄存器,每组寄存器可以单独产生定时。 所以,真正可用的普通定时器有4个:TIMER0-0、TIMER0-1、TIMER1-0、TIMER1-1。 4个定时器均可独立设置。 普通定时器特点:
定时器支持16位和32位的设置, 支持3种类型分频(1分频,16分频,256分频), 支持单次定时和循环定时。
驱动API函数命名中的1和2,分别对应第一组和第二组寄存器。也就是说,一个Timer可以用于2个独立计时器。 如,TIM_Init1设置的是第一组寄存器,TIM_Init2设置的是第二组寄存器。
举例: 用Timer1的group2产生1s的循环定时:
中断函数TIMER1_isr在SDK中已经默认指定。 说明: 设置函数:TIM_Init1 <-> TIM_SetLoad1/TIM_SetSize1/TIM_SetMode1/... 中断函数:TIMER0_isr/TIMER1_isr 函数说明: void TIM_Init1(TIMER_TypeDef *tim, uint32_t timeInUs, TIMER_ModeTypeDef mode) 作用:启动Timer0或Timer1的第一个定时器(TIM_Init2则启动第二个定时器)。 参数:tim:TIMER0 or TIMER1 timeInUs:多少us触发定时 mode:TIMER_MODE_PERIODIC:循环触发 TIMER_CTRL_ONESHOT:只触发一次 举例: TIM_Init1(TIMER0, 500000, TIMER_MODE_PERIODIC); 表示启动TIMER0的第一个定时器,500ms触发一次定时中断,循环触发。 除了直接调用 TIM_Init1来启动一个定时外,也可以调用各个子函数来启动。 如, TIM_Init2(TIMER0, 500000, TIMER_MODE_PERIODIC) 功能等价于:
TIM_SetLoad2(TIMER0, SYS_GetPclkFreq() / 1000000 * 500000); TIM_SetSize2(TIMER0, TIMER_SIZE_32); TIM_SetMode2(TIMER0, TIMER_MODE_PERIODIC); TIM_SetPrescaler2(TIMER0, TIMER_PRESCALE_1); TIM_EnableInt2(TIMER0); TIM_EnableTimer2(TIMER0);
以上几个函数中, TIM_SetPrescaler2 是设置分频, 三个参数可选:TIMER_PRESCALE_1/TIMER_PRESCALE_16/TIMER_PRESCALE_256 分别表示分频数:1分频,16分频,256分频; TIM_SetSize2 设置计时器位宽, 两个参数可选:TIMER_SIZE_32/TIMER_SIZE_16 表示计数器的load的位宽是32位还是16位。 TIM_SetLoad2 设置触发时间(以tick为单位) 如果定时单位为ms,则需要将tick转为ms:SYS_GetPclkFreq()/1000000*ms 中断函数:void TIMER0_isr() 函数说明:该函数为TIMER0的中断函数; 在该函数中需要先查询是第一个还是第二个定时器,然后再清中断。 该中断函数已默认关联,不需要程序中来手工设置。 完整代码样例请参考example下example_timer.c。
六、gpTimer的使用:General Purpose Timer,即通用计时器。相当于ST中的Advanced Timer. AG32中包含5个通用计时器(GpTimer), 代码中分别对应:GPTIMER0、GPTIMER1、GPTIMER2... 通用定时器可以实现更多功能,包括:计时、生成pwm、生成任意波形、输入捕获。 5个定时器均可独立设置。 每个定时器支持4个独立通道(channel): -- 输入捕获 -- PWM输出(边缘或中间对齐模式) -- 单脉冲输出 主要函数:GPTIMER_Init / GPTIMER_OC_Init.
1、用于简单定时用于简单定时,只需要关注一个函数:GPTIMER_Init, 设置好参数后,启动计时即可。 举例: 用gpTimer1产生2秒一次的定时。
这里使用到的中断函数GPTIMER1_isr,已被SDK自动设置。
2、用于pwm输出用于pwm输出时,要设置两个函数:GPTIMER_Init 和 GPTIMER_OC_Init。 GPTIMER_Init中设置多长时间触发一次timer; GPTIMER_OC_Init中指定pwm输出通道及设置pwm的占空比; 举例: 用gpTimer4在通道0上产生pwm输出。
除了上述的代码控制外,还需要在ve中添加映射关系:
这样的情况下,pwm才会输出到管脚上。 典型案例:呼吸灯(用timer+timerPWM来控制led灯逐渐变量逐渐变暗)
3、输出反向PWM(带死区)样例程序,请参考网盘下“其他文档\驱动样例补充\example_gptimer_pwm_N.c”
4、输出任意波形如果要输出的不是pwm的规则波形,而是不规则波形(比如正弦波),则可借助于DMA方式来模拟实现。 思路:事先在数组中定义好数据序列,然后通过dma每次搬运,作用到输出。 这部分功能,参考例程函数:TestGpTimerDma 这种方式也同样需要管脚映射。
5、用于输入捕获用于输入捕获时,要设置两个函数:GPTIMER_Init 和 GPTIMER_IC_Init。 样例程序,请参考网盘下“其他文档\驱动样例补充\example_gptimer_capture.c”
七、Uart的使用AG32可用的UART有5个,分别对应UART0、UART1、UART2、UART3、UART4。几个Uart的功能和用法是完全相同的。 样例工程中,UART0被做为输出log的串口。其他几个UART可被用户直接使用。 串口使用较为简单,这里讲述下几个重要函数: 初始化函数: void UART_Init(UART_TypeDef *uart, UART_BaudRateTypeDef baudrate, UART_LCR_DataBitsTypeDef databits, UART_LCR_StopBitsTypeDef stopbits, UART_LCR_ParityTypeDef parity, UART_LCR_FifoTypeDef fifo) 参数说明: - Uart:UART0、UART1、UART2、UART3 or UART4
- Baudrate:波特率,如 115200
- Databits/stopbits/parity:
- Fifo:是否开启16字节的fifo缓冲
收发函数: - UART_Send(UART_TypeDef *uart, const unsigned char *p, unsigned int num)
- UART_Receive(UART_TypeDef *uart, unsigned char *p, unsigned int num, unsigned int timeout)
- 收函数的timeout,是如果收不满num个字符,就等待多少个tick。可以为0。
样例1、实现Uart1的简单收发
代码中实现如下:
样例2、使用接收中断(8字节)来收取数据 这种方式,是使用了FIFO的收中断;(可配置 收到2/4/8/12/16 bytes时触发中断) 代码部分可参考以下方式(新增的红框代码):
中断函数UART1_isr在SDK中已经默认关联,不用手动设置。 在中断函数中,要判别中断来源再继续操作。 上例中,收FIFO因为设置为16字节,半数触发时,收到8个字节就会触发中断。
样例3、使用接收中断(1字节)来收取数据 相比样例2,如果想要来1个字节就触发一次中断,可以使用这里的方式。 代码方面:在UART_Init中设置参数为UART_LCR_FIFO_1,并且不用再调UART_SetRxIntFifoLevel函数。
样例4、使用DMA收发 如果要启用DMA功能,参考sdk中自带的样例。 需要增加3个函数: DMAC_Init:启动dma UART_SetDmaMode:设置只要收/发dma,或收发都要dma DMAC_Config:设置dma的详细参数。
如果收发都要dma,则需要调用2次DMAC_Config来分别设置。 函数DMAC_Config的参数说明: void DMAC_Config( DMAC_ChannelNumTypeDef channel, //DMA通道 uint32_t srcAddr, //DMA数据源地址 uint32_t dstAddr, //DMA数据目标地址 DMAC_AddrIncTypeDef srcIncr, //传输后源地址是否自增 DMAC_AddrIncTypeDef dstIncr, //传输后目标地址是否自增 DMAC_WidthTypeDef srcWidth, //源地址传输数据的字节宽度(可选8/16/32) DMAC_WidthTypeDef dstWidth, //目标地址传输数据的字节宽度(可选8/16/32) DMAC_BurstTypeDef srcBurst, //源地址一次传输多少 DMAC_BurstTypeDef dstBurst, uint32_t transferSize, //传输多少次 DMAC_FlowControlTypeDef transferType, //传输方向类型(8种) uint32_t srcPeripheral, //源地址的外设类型 uint32_t dstPeripheral //目标地址的外设类型 ) 比如,设置收DMA,会设置参数如: DMAC_Config(DMAC_CHANNEL1, (uint32_t)&UART3->DR, //串口数据寄存器 (uint32_t)rxbuf, //收缓冲buff DMAC_ADDR_INCR_OFF, //源地址不自增 DMAC_ADDR_INCR_ON, //目标地址自增 DMAC_WIDTH_8_BIT, //源数据宽度以8bit为单位 DMAC_WIDTH_8_BIT, //目标数据宽度以8bit为单位 DMAC_BURST_1, DMAC_BURST_1, 0, //传输多少次,如果是0则无限制 DMAC_PERIPHERAL_TO_MEM_PERIPHERAL_CTRL, //外设到内存的方向 UART3_RX_DMA_REQ, //源数据外设类型 0 ); //目标数据外设类型 设置发的DMA,会设置参数如: DMAC_Config(DMAC_CHANNEL0, (uint32_t)txbuf, //发缓冲 (uint32_t)&UART3->DR, //串口数据寄存器 DMAC_ADDR_INCR_ON, //发缓冲自增 DMAC_ADDR_INCR_OFF, //寄存器不自增 DMAC_WIDTH_8_BIT, //源数据宽度以8bit为单位 DMAC_WIDTH_8_BIT, //目标数据宽度以8bit为单位 DMAC_BURST_1, DMAC_BURST_1, dma_count, //要传输的数据量 DMAC_MEM_TO_PERIPHERAL_DMA_CTRL, //内存到外设的方向 0, //源数据外设类型 tx_dma_req); //目标数据外设类型 以上完整代码样例请参考example部分。
更多样例,请参考网盘 1).dma中断:“其他文档\驱动样例补充\example_uart_dmaIrq.c” 2).闲时中断:“其他文档\驱动样例补充\example_uart_rcvIqr.c”
八、IIC的使用AG32支持两路I2C,分别对应:I2C0、I2C1; I2C是一种简单的双向两线制总线协议,半双工,支持多主从模式。I2C最大的特点之一就是有完善的应答机制。 MCU端是I2C的主端。 样例程序参考example_i2c.c 在使用I2C时的流程: 1. Ve中先配置对应的引脚:
2. 代码中时钟使能、中断使能、设置频率;
3. 使能I2C;
4. 收发数据; IIC的收过程和发过程,都有对应的应答流程,启动->收/发->结束。 使用中,收发函数会被完整的封装。 请参考例程函数(函数流程可参考,封装请自行调整): bool I2cReadPROM(uint8_t *mem, bool verify) bool I2cWritePROM(uint8_t *mem)
5. 关闭I2C:
另外,例程中还使用到了中断函数。当I2C准备好时,会触发该中断。 注意,IIC例程需要接入设备才能测通,否则在I2C_WaitForTransfer函数中会因为等不到Ack而卡住。 . 九、CAN的使用AG32支持1路CAN,对应:CAN0 样例程序参考example_can.c 在使用CAN时的流程:
2. 代码中使能时钟、开中断:
3. 配置参数(参数较多)并开启can、开启收中断:
4. 发送数据:
5. 在中断函数中接收数据:
使用时,请参考样例修改。
联系海振远科技 电话:0755-2780 9180; 15323895320; Lucy@hizyuan.com
|