Linux-Ubuntu之裸机驱动最后一弹PWM控制显示亮度
- [一, PWM实现原理](#一, PWM实现原理)
- 二,软件实现
- 三,正点原子裸机开发总结
一, PWM实现原理
PWM和学习51时候基本上一致,控制频率(周期)和占空比,51实验是利用中断进行控制的,在中断中设置计数,低于占空比设定值,会让引脚一直为高电平,高于的话,让引脚为低电平,用周期数值限制,但是这个简单的地方在于能直接控制高低电平。在这个板子上,主要是控制寄存器值,有频率相关寄存器PWMx_PWMPR,向上计数器从0开始计数,一直加一,当等于这个PWMx_PWMPR设定的值,就实现一个周期,然后再从0开始计数。占空比相关寄存器 PWMx_PWMSAR,默认高电平时,向上计数器值等于FIFO值,就会使得PWM引脚输出低电平,FIFO的值就是来源于PWMx_PWMSAR,因此这个PWMx_PWMSAR值越大,相当于占空比越高。从采样寄存器 PWMx_PWMSAR 读取一次数据,FIFO 里面的数据就会减一,每产生一个周期的 PWM 信号,FIFO 里面的数据就会减一,相当于被用掉了。PWM 有个 FIFO 空中断,当FIFO 为空的时候就会触发此中断,可以在此中断处理函数中向 FIFO 写入数据,这个实验就利用了中断,在中断函数中,实现对PWMSAR写数据。
寄存器配置包括时钟源,分频值,周期寄存器PWMx_PWMPR,采样寄存器PWMx_PWMSAR,中断控制,相关使能。
二,软件实现
PWM函数:
c
/*pwm.h*/
#ifndef _DSP_PWM_H
#define _DSP_PWM_H
#include "imx6ul.h"
struct pwm_period_and_rate_struct
{
unsigned char pwm_rate;//占空比
};
extern struct pwm_period_and_rate_struct pwm_dev;
void pwm_init(void);
void pwm1_fifo_irqhandler(unsigned int gocciar,void *param);
void pwm1_period_set(unsigned int value);
void pwm1_rate_set(unsigned char rate);
#endif
/*pwm.c*/
#include "dsp_pwm.h"
#include "dsp_int.h"
struct pwm_period_and_rate_struct pwm_dev;
/*初始化*/
void pwm_init(void)
{
/*1.引脚初始化*/
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_PWM1_OUT,0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_PWM1_OUT,0XB090);
/*2.PWM初始化,时钟源60MHZ,分频1000,*/
PWM1->PWMCR = 0;
PWM1->PWMCR |=(1<<16)|(65<<4)|(1<<26);
/*3.设置周期和占空比*/
unsigned int i=0;
pwm1_period_set(1000);//设置频率为1000KHZ(周期)
pwm_dev.pwm_rate=50;
for(i=0;i<4;i++)
{
pwm1_rate_set( pwm_dev.pwm_rate);//默认占空比为50,因为有四个FIFO,所以写四次
}
/*4.使能FIFO空中断*/
PWM1->PWMIR |= 1<<0;
system_register_irqhandler(PWM1_IRQn,(system_irq_handler_t)pwm1_fifo_irqhandler,NULL);
GIC_EnableIRQ(PWM1_IRQn);/*FIFO引起的中断*/
PWM1->PWMSR |= (1<<3);//中断标志位写1清0
/*5.使能PWM*/
PWM1->PWMCR |=1<<0;
}
/*中断处理函数*/
void pwm1_fifo_irqhandler(unsigned int gocciar,void *param)
{
if(PWM1->PWMSR & (1<<3))//FIFO空中断
{
pwm1_rate_set(pwm_dev.pwm_rate);
PWM1->PWMSR |= (1<<3);//中断标志位写1清0
}
}
/*设置周期*/
void pwm1_period_set(unsigned int value)
{
unsigned int model_value =0;
if (value<2)
{
model_value = 2;
}else model_value = value -2;
PWM1->PWMPR = model_value&0xffff;
}
/*设置占空比*/
void pwm1_rate_set(unsigned char rate)
{
unsigned short model_rate;
pwm_dev.pwm_rate = rate;//将占空比写入结构体定义的值中
unsigned int period = PWM1->PWMPR + 2;
model_rate=(unsigned short )(period*(rate/100.0f));//将0-100转化为占空比放入寄存器第真实值
PWM1->PWMSAR =model_rate & 0xffff;
}
主函数:
c
#include "main.h"
#include "dsp_clk.h"
#include "dsp_led.h"
#include "dsp_delay.h"
#include "beep.h"
#include "dsp_key.h"
#include "dsp_int.h"
#include "dsp_exti.h"
#include "dsp_epit.h"
#include "dsp_uart.h"
#include "stdio.h"
#include "dsp_lcd.h"
#include "dsp_lcdapi.h"
#include "dsp_rtc.h"
#include "dsp_i2c.h"
#include "dsp_ap3216c.h"
#include "dsp_spi.h"
#include "dsp_icm20608.h"
#include "dsp_pwm.h"
void imx6ul_hardfpu_enable(void)//使能浮点数运算
{
uint32_t cpacr;
uint32_t fpexc;
/* 使能NEON和FPU */
cpacr = __get_CPACR();
cpacr = (cpacr & ~(CPACR_ASEDIS_Msk | CPACR_D32DIS_Msk))
| (3UL << CPACR_cp10_Pos) | (3UL << CPACR_cp11_Pos);
__set_CPACR(cpacr);
fpexc = __get_FPEXC();
fpexc |= 0x40000000UL;
__set_FPEXC(fpexc);
}
int main(void)
{
unsigned char kkkk=0,rate=0;
unsigned int key_result;
imx6ul_hardfpu_enable();//打开浮点运算
int_init();//中断初始化
imx6u_clkinit();//时钟初始化
key_init();//按键初始化
clk_enable();//时钟初始化
uart_init();//串口初始化
beep_init();//凤鸣器初始化
led_init();//led初始化
lcd_init();//LCD读ID号
rtc_init();//RTC初始化
ap3216c_init();//传感器初始化
icm20608_init();//加速度计 陀螺仪等传感器初始化
pwm_init();//PWM初始化
tftlcd_dev.forecolor = LCD_RED;
tftlcd_dev.backcolor = LCD_WHITE;
while(1)
{
key_result = key_value();
if(key_result == 0)
{
rate +=10;
if(rate>110)
{
rate=0;
}
printf("占空比 = %d\r\n",rate);
pwm1_rate_set(rate);
}
led_mode(kkkk);
delay(1000);
kkkk = !kkkk;
}
return 0;
}
三,正点原子裸机开发总结
从12.5号到1.6号,中间去海南出差17天,耗时差不多一个月,把这个正点原子的二期视频给看完,程序都敲了一遍,感觉比51是难上一成,51学了20天,看完视频基本上能自己把代码完整敲完,不用对着,这个真整不了,说是裸机开发,感觉更像是学习寄存器控制,好多好多寄存器的位要去控制,还要去函数嵌套,实现各种功能,不过也学习了各种C语言的知识,像宏还能去利用函数,枚举类型和结构体的嵌套,各种函数的调用,指针和数组的使用很多吧。做过的实验有内核时钟控制,定时器和中断的使用,串口通信,DDR内存的使用,I2C和SPI控制显示屏的各种操作,还有像小杂的PWM,按键,灯,蜂鸣器等等吧,算是对这些硬件设备有了一个新的了解,真正的怎么样从内部去使用它,不过这些只是简单的入门,或者说现在还没入上门,哈哈哈哈哈。
2-3月这个月计划把系统移植这部分给整完,真正需要学的还在驱动开发上,现在还差一段距离,不知道过年回家了,还有心思学不,继续冲鸭,整完,过个好年!!!