以下内容是我在学习K60时的部分模块时的小结
注意:当程序需要运行浮点型数据时,要加入开启硬件浮点的代码:(放入 start 函数 的 mian函数之前即可!!!start 函数在 Chip\src\IAR\system_MK60DZ10.c 文件里定义
#if MK60F15
SCB->CPACR |=((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access 开硬件浮点型*/
#endif
1.gpio模块:
gpio_init (PTA8, GPI,0); //初始化 PTA8 管脚为输入(低电平)
gpio_ddr (PTA8, GPI); //设置 PTA8 管脚为输入
gpio_set (PTA8, 1); // PTA8 管脚为高电平
uint8 pta8_data=gpio_get (PTA8);// 获取 PTA8 管脚 输入电平(应保持管脚为输入状态)
gpio_turn (PTA8); // PTA8 管脚 输出 反转(应保持管脚为输出状态)
/////////////////////////////////////////////////////////////////////////////////////////////
// 如果以上四条为大写的情况,则管脚不能是变量
// 即:
// GPIO_SET(PTxn,data) (PTXn_T(PTxn,OUT)= (data)) //设置输出电平
// GPIO_TURN(PTxn) (PTXn_T(PTxn,T)= 1) //翻转输出电平
// GPIO_GET(PTxn) (PTXn_T(PTxn,IN)) //读取引脚输入状态
// GPIO_DDR(PTxn,ddr) (PTXn_T(PTxn,DDR) = ddr) //输入输出状态
// 中的PTxn应为定值,不能是变量。
/////////////////////////////////////////////////////////////////////////////////////////////
//对多位的端口一起进行操作
GPIO_SET_NBIT(8,PTA8,255); //PTA8以及其后7位管脚,同时被设置为:高电平
GPIO_DDR_NBIT(8,PTA8,255) //PTA8以及其后7位管脚,同时被设置为:输出
GPIO_T_NBIT(NBIT,PTxn,data)
GPIO_GET_NBIT(8,PTA8); //同时读取PTA8以及其后7位管脚的电平高低
//对寄存器的为操作
PTA8_DDR==PT(A,8,PDDR)==PTXn_T(PTxn(只能宏定义,不能是变量),DDR)
PTA8_IN ============PT(A,8,PDIR)
PTA8_T ============PT(A,8,PTOR)//翻转PTA8的电平输出端口(=1为翻转)
//32位操作
PTA_OUT=============PT_DWORD(A,PDOR)
PTA_IN =============PT_DWORD(A,PDIR)
PTA_DDR=============PT_DWORD(A,PDDR)
//定义PTA的16位输出反转:PTA_W0_T PT_WORD(A,0,PTOR)
//定义PTA的16位输入端口:PTA_W0_IN PT_WORD(A,0,PDIR)
//定义PTA的16位输出输入方向端口:PTA_W0_DDR PT_WORD(A,0,PDDR)
//定义PTA的16位端口:PTA_W0_OUT PT_WORD(A,0,PDOR)
//8位操作:PTA_B0_T======================PT_BYTE(A,0,PTOR)..........
port_init (PTA8, IRQ_RISING | PF | ALT1 | PULLUP ); //初始化 PTA8 管脚,上升沿触发中断,带无源滤波器,复用功能为 GPIO ,上拉电阻
port_init_NoALT(PTA8, IRQ_RISING | PF | PULLUP ); //初始化 PTA8 管脚,上升沿触发中断,带无源滤波器,上拉电阻(用于初始化引脚,不改变原有的MUX复用功能)
外部中断:
porta_handler(void);
//假设 PTA7 需要执行的用户任务函数为 func() ,则可以直接调用如下宏定义:PORT_FUNC(A,7,func);
用法举例:
(1) void porta_handler(void)
{
uint8 n = 0; //引脚号
//PTA6
n = 6;
if (PORTA_ISFR & (1 << n)) { //PTA6 触发中断
PORTA_ISFR = (1 << n); //写 1 清中断标志位
/* 以下为用户任务 */
key();
/* 以上为用户任务 */
}
}
(2) void porta_handler(void)
{
PORT_FUNC(A,6,key);//PTA6触发中断,执行用户函数key
}
2.LED模块:
led_init (LED0); //初始化 LED0
led (LED0,LED_ON); //点亮 LED0
led_turn (LED0); // LED0灯亮灭反转
3.UART模块:
uart_init (UART1,19200); //初始化 串口 1 波特率为 19200
uart_getchar (UART3,&ch); //等待接收 1 个字节,保存到 ch 里
uart_querychar (UART3,&ch) == 1 //查询接收通信缓冲区内 1 个字符,保存到 ch 里;查询接收 1 个字符,若接收到数据则返回1并存储到ch形参指向的地址,否则返回0
uint32 num = uart_querystr(UART3,&str,100-1);//在最大可存储字节上减一字节空出给’\0;返回接收到的字节数
uint32 uart_querybuff (UARTn_e, char *buff, uint32 max_len)//参照uart_querystr,唯一不同是不会因为遇到字符串结尾标志’\0’而退出,会持续读取通讯缓冲区直到规定的最大值max_len
if(uart_query(UART3) == 1) //查询是否接收到数据
uart_putchar (UART3, ‘A’); //发送字节’A
uart_putbuff (UART3,”1234567”, 3); //实际发送了 3 个字节’1’,’2’,’3’
uart_putstr (UART3,”1234567”); //实际发送了 7 个字节
uart_rx_irq_en (UARTn_e); //开串口接收中断
uart_rx_irq_dis(UARTn_e); //关串口接收中断
uart_tx_irq_en (UARTn_e); //开串口发送中断
uart_tx_irq_dis(UARTn_e); //关串口发送中断
uart_txc_irq_en (UARTn_e); //开串口发送完成中断
uart_txc_irq_dis(UARTn_e); //关串口发送完成中断
4.I2C模块:(没有实测过,但看论坛里说自带的IIC模块不是很好用,容易受影响)
i2c_init(I2C0,400*1000); // 初始化 I2C0,期待的波特率为 400k
i2c_write_reg(I2C0, 0x1D, 1,2); //向从机 0x1D 的寄存器 1 写入数据 2
uint8 value = i2c_read_reg(I2C0, 0x1D, 1);//读取 I2C 设备指定寄存器的一个字节数据
5.SPI模块:
uint32 baud = spi_init(SPI0,SPIn_PCS0, MASTER,10*1000*1000);//初始化 SPI,选择 CS0,主机模式, 波特率为 1M ,返回真实波特率到 baud 变量
void spi_mosi(SPI0,SPIn_PCS0,buff,buff,2); //发送 buff 的内容,并把接收的数据存放到 buff 里,长度为 2 字节
spi_mosi_cmd (SPI0,SPIn_PCS0,cmd,NULL,buff,buff,1,2);//发送 cmd/buff 的内容,不接收 cmd 发送时的数据,接收 buff 发送时的数据到 buff 里,长度分别为 1、 2 字节
PS:发送和接受的存储地址可用同一个,先发送存储地址中的8位数据到从机SPI缓冲区,然后从接收缓冲区中将接收的数据写入存储地址(覆盖发送的数据)。
6.ADC模块:
adc_init (ADC0_SE10 ); //初始化 ADC0_SE10 , K60 使用 PTA7 管脚
uint16 var = adc_once(ADC0_SE10, ADC_8bit);//采样一次一路模拟量的 AD 值,返回采样数值。按采集精度来返回不同大小, 16 位精度最大返回: 65535
adc_stop(ADC0);//停止 ADC 模块的 AD 转换,同一个模块的所有通道都会停止。
7.DAC模块:
dac_init (DAC0 ); //初始化 DAC0
dac_out (DAC0 ,0x100); //初始化 DAC0 输出 0x100 数字量对应的模拟量: 3300*(1 + 0x100)/4096 mV
8.FTM(高级定时器模块、易用定时器模块)
(1)pwm模块:
ftm_pwm_init(FTM0, FTM_CH6,200, 10); //初始化 FTM0_CH6 为 频率 200Hz 的 PWM,占空比为10/FTM0_PRECISO
(同一个FTM,各通道的PWM频率是一样的,但占空比可不一样)
ftm_pwm_duty(FTM0, FTM_CH6, 10);//设置 FTM0_CH6 占空比为 10/FTM0_PRECISON
ftm_pwm_freq(FTM0,200);//设置 FTM0 的 频率 为 200Hz
(改频率后,需要重新配置占空比)
(2)输入捕捉模块:
ftm_input_init(FTM0,FTM_CH0,FTM_Rising,FTM_PS_2);//设置 FTM0_CH0 上升沿触发输入捕捉,二分频
uint16 data = ftm_input_get (FTM0, FTM_CH0);// 获取 FTM0_CH0 输入捕捉事件触发时的计数值
ftm_input_clean(FTMn_e );//清空计数器的值。即计数器重新开始计数。
FTM1_Input_test_handler(void)//中断函数
(3)正交解码:(用此模块时,FTM1的两个通道都要连接)
ftm_quad_init(FTM1);//初始化 FTM1 为正交解码模式
int16 count = ftm_quad_get(FTM1);//获取 FTM1 交解码 的脉冲数
ftm_quad_clean(FTM1);//复位 FTM1 正交解码 的脉冲数
9.PIT(定时模块)
(1)定时中断:
pit_init(PIT0, 1000); //定时 1000 个 bus 时钟 后中断
[
pit_init_ms(PITn_e,ms) //初始化 PITn,并设置定时时间(单位为 ms)
pit_init_us(PITn_e,us) //初始化 PITn,并设置定时时间(单位为 us)
pit_init_ns(PITn_e,ns) //初始化 PITn,并设置定时时间(单位为 ns)
]
set_vector_handler(PIT0_VECTORn,pit_hander); // 设置中断服务函数到中断向量表里
enable_irq(PIT0_IRQn); // 使能 PIT 中断
//PIT_Flag_Clear(PIT0);//清 PITn 中断标志。一般在中断服务函数和 pit 初始化函数里用到
(2)计时:
pit_time_start(PIT0); //PIT0 计时开始
uint32 time = pit_time_get(PIT0); //获取 PITn 计时时间
(获取 PITn 计时时间并返回(超时时会关闭 定时器)(单位为 bus 时钟) (若值为0xFFFFFFFF,则表示超时溢出))
[.........]
pit_close(PIT0); //关闭 PIT0
(3)延时:
pit_delay(PIT0, 1000);//延时 1000 个bus时钟
[
(不需要初始化,可直接调用)
pit_delay_ms(PITn_e,ms) //PIT 延时 ms
pit_delay_us(PITn_e,us) //PIT 延时 us
pit_delay_ns(PITn_e,ns) //PIT 延时 ns
]
10.lptmr(低功耗定时器)
注意:LPTMR模块的计数寄存器虽然是32位的但是31-16位是只读预留位,始终为0,所以计数时最大数字只能有16位
(1)延时:
lptmr_delay_ms(32); // LPTMR 延时 32ms
lptmr_delay_us(32); // LPTMR 延时 32us
(2)定时:
lptmr_timing_ms(32); // LPTMR 定时 32ms
lptmr_timing_us(32); // LPTMR 定时 32us
set_vector_handler(LPTimer_VECTORn,lptmr_hander); // 设置中断服务函数到中断向量表里
enable_irq(LPTimer_IRQn); // 使能 LPTMR 中断
(3)计时:
lptmr_time_start_ms(void);//开始计数
uint32 lptmr_time_get_ms(void); //获取计数时间( 不同的开始计时单位,需要配套相应不同的获取计时时间单位函
[.....us.....]
void lptmr_time_close(); //关闭 LPTMR 计时
(4)脉冲技术:
lptmr_pulse_init(LPT0_ALT1,0xFFFF,LPT_Rising);// LPTMR 脉冲计数, 计数 0xFFFF 后触发中断请求(需要开中断才执行中断服务函数),上升沿捕捉
uint16 data = lptmr_pulse_get(); //获取脉冲计数值
lptmr_counter_clean(); //清空 LPTMR 脉冲计数
11.DMA模块:
dma_portx2buff_init(DMA_CHn, void *SADDR, void *DADDR, PTXn_e, DMA_BYTEn, uint32count, uint32 cfg); //初始化 DMA,使得 PORT 端口数据通过 DMA 传输到 BUFF 缓冲区
ps:用到的输入端口和触发端口已经内部初始化,不需要再额外初始化。默认触发端口为上升沿触发,如果需要配置为下降沿触发,可调用 port_init 函数来重新配置。
dma_repeat(DMA_CHn CHn,void *SADDR, void *DADDR,uint32 count) //DMA 重新配置,传输完毕后,一些参数会改变,需要重新赋值。
ps:DMA 的目的地址每次传输都会加一,有时不需要加一可以使用此函数复位
DMA_IRQ_EN(DMA_CH3); //允许 DMA 通道 3 传输完成中断
DMA_IRQ_DIS(DMA_CH3); //禁止 DMA 通道 3 传输完成中断
DMA_IRQ_CLEAN(DMA_CH3); //清除 DMA 通道 3 传输中断标志位(一般用于中断程序中)
DMA_EN(DMA_CH3); //使能 DMA 通道 3 硬件 DMA 请求
DMA_DIS(DMA_CH3); //禁止 DMA 通道 3 硬件 DMA 请求