• I.MX6U-ALPHA开发板(PWM实验)


    文章目录

    PWM简介

    1、6ULL的PWM是16位计数器,
    2、有4个16位的FIFO
    3、一个12位的分频
    4、正点原子LCD屏幕的背光IO连接到了GPIO1_IO08上。

    GPIO1_IO08可以复用位PWM1_OUT信号。

    PWM计数器从0X0000开始计数,当计数器的值等于PWMPR+1的时候定时器就会重新开始下一个周期的运行,因此PWMPR寄存器控制着PWM频率。

    FIFO保存着采样值,当我们向PWMSAR寄存器写采样值的时候会写道FIFO里面,内每当读取一次PWMSAR寄存器,FIFO里面的数据都会减一,或者每产生一个PWM信号,FIFO的数据也会减一。直到FIFO为空,那么就无法再产生PWM信号。FIFO为空的时候会产生中断,我们可以在中断中向FIFO写入采样数据,也就是向PWMSAR写数据。

    PWMCR寄存器,bit0是PWM使能信号,bit2:1设置为0,每个周期使用FIFO里面的一个数据。Bit15:4,PWM分频设置,可以设置04095,对应14096分频。Bit17:16设置PWM时钟源,设置为1,表示使用ipg_clk=66MHz。bit19:18,设置为0。Bit27:26,设置为01,表示当FIFO里面空余位置大于2的时候FIFO为空。

    PWMIR寄存器,bit0设置为1,开启FIFO空中断。

    //bsp_bmp280.h
    
    #ifndef _BSP_BMP280_H
    #define _BSP_BMP280_H
    #include "imx6ul.h"
    #include "bsp_gpio.h"
    
    /* 宏定义 */
    #define BMP280_CSN(n)    (n ? gpio_pinwrite(GPIO1, 20, 1) : gpio_pinwrite(GPIO1, 20, 0))   //SPI片选信号	
    
    #define	BMP280_ID_VALUE			0X58	/* BMP280 ID值				*/
    #define BMP280_RESET_VALUE		0XB6	/* BMP280复位值 				*/
    
    
    /* BMP280寄存器宏定义 */
    #define	BMP280_TEMPXLSB_REG		0XFC	/* 温度值的bit[3:0]寄存器			*/
    #define BMP280_TEMPLSB_REG		0XFB	/* 温度值的bit[11:4]寄存器 		*/
    #define BMP280_TEMPMSB_REG		0XFA	/* 温度值的bit[19:12]寄存器		*/
    #define BMP280_PRESXLSB_REG		0XF9	/* 压力值的bit[3:0]寄存器			*/
    #define BMP280_PRESLSB_REG		0XF8	/* 压力值的bit[11:4]寄存器 		*/
    #define BMP280_PRESMSB_REG		0XF7	/* 压力值的bit[19:12]寄存器  		*/
    #define BMP280_CONFIG_REG		0XF5	/* 配置寄存器 					*/
    #define BMP280_CTRLMEAS_REG		0XF4	/* 测量配置寄存器 					*/
    #define BMP280_STATUS_REG		0XF3	/* 状态寄存器 					*/
    #define BMP280_RESET_REG		0XE0	/* 复位寄存器 					*/
    #define BMP280_ID_REG			0XD0	/* ID寄存器 					*/
    
    #define BMP280_TRIMPARAM_FRG	0X88	/* 参数组寄存器首地址 				*/
    #define BMP280_TRIMPARAM_LEN	24		/* 参数组寄存器长度 				*/
    
    #define BMP280_INVALID_DATA		0		/* 无效的数据 					*/
    
    /*
     * BMP280 参数结构体
     */
    struct bmp280_calib_param 
    {
    	unsigned short 	dig_T1;		/* T1参数	*/
    	short 		 	dig_T2;		/* T2参数 */
    	short 			dig_T3;		/* T3参数	*/
    	unsigned short  dig_P1;		/* P1参数 */
    	short 			dig_P2;		/* P2参数 */
    	short 			dig_P3;		/* P3参数 */
    	short 			dig_P4;		/* P4参数 */
    	short 			dig_P5;		/* P5参数 */
    	short 			dig_P6;		/* P6参数 */
    	short 			dig_P7;		/* P7参数 */
    	short 			dig_P8;		/* P8参数 */
    	short 			dig_P9;		/* P9参数 */
    	signed int 		t_fine;		/* t_fine参数*/
    };
    
    /*
     * BMP280结构体
     */
    struct bmp280_dev_struc
    {
    	struct bmp280_calib_param calib_param;
    
    	signed int uncomp_temp;		/* 原始的温度值 */
    	signed int uncomp_pres;		/* 原始的压力值 */
    	signed int actual_temp;		/* 真实的温度值 */
    	signed int actual_pres;		/* 真实的压力值 */
    	
    };
    
    extern struct bmp280_dev_struc bmp280_dev; 
    
    /* 函数声明 */
    unsigned char bmp280_init(void);
    unsigned char bmp280_read_reg(unsigned char reg);
    void bmp280_read_len(unsigned char reg, unsigned char *buf, unsigned char len);
    void bmp280_write_reg(unsigned char reg, unsigned char value);
    void bmp280_get_calibparam(void);
    signed int bmp280_get_uncomptemp(void);
    signed int bmp280_get_uncomppres(void);
    signed int bmp280_get_actualtemp(signed int uncomptemp);
    unsigned int bmp280_get_actualpres(s32 uncomppres);
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    //bsp_bmp280.c
    
    #include "bsp_bmp280.h"
    #include "bsp_delay.h"
    #include "bsp_spi.h"
    #include "stdio.h"
    
    /* BMP280属性结构体 */
    struct bmp280_dev_struc bmp280_dev; 
    //初始化BMP280
    //返回0 初始化成功,其他值 初始化失败
    unsigned char bmp280_init(void)
    {	
    	unsigned char regvalue;
    	gpio_pin_config_t cs_config;
    	
    	/* 1、初始化SPI */
    	spi3_init();	
    	
    	/* 2、初始化片选引脚 */
    	IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0);
    	IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0X10B0);
    	cs_config.direction = kGPIO_DigitalOutput;
    	cs_config.outputLogic = 1;
    	gpio_init(GPIO1, 20, &cs_config);
    	
    	/* 4、配置BMP280 */
    	regvalue = bmp280_read_reg(BMP280_ID_REG);/* 读取ID */
    	if(regvalue == BMP280_ID_VALUE)
    	{
    		printf("bmp280 id = %#X\r\n", regvalue);
    	} else {
    		return 1;
    	}
    	
    	bmp280_write_reg(BMP280_RESET_REG, BMP280_RESET_VALUE); /* 复位BMP280 */
    	bmp280_write_reg(BMP280_CTRLMEAS_REG, 0);				/* 进入睡眠模式才可以写控制寄存器 */
    
    	/* 设置BMP280使用Ultra high     resolution模式,即:
         * osrs_p为X16,osrs_t为X2,IIR Filter为16
    	 */
    
    	/* 
    	 *配置BMP280控制寄存器CONFIG_REG
    	 *bit[7:5]	: 000 normal模式下的T_standby,0.5ms
    	 *bit[4:2]	: 111 IIR滤波器的时间常量 X16 
    	 *bit[0]	: 0 禁止3线SPI模式
    	 */
    	bmp280_write_reg(BMP280_CONFIG_REG, 0x1C);
    
    	/* 
    	 *配置BMP280测量寄存器CTRLMEAS_REG
    	 *bit[7:5]	: 010 温度采样率x2	 17bit/0.0025°C
    	 *bit[4:2]	: 111 压力采样率x16 20bit/0.16Pa 
    	 *bit[1:0]	: 11 normal模式 
    	 */
    	bmp280_write_reg(BMP280_CTRLMEAS_REG, 0x5F);			
    
    	bmp280_get_calibparam();	/* 计算参数 */
    
    	return 0;
    }
    
    //计算BMP280的计算参数
    void bmp280_get_calibparam(void)
    {
    	unsigned char param_buf[BMP280_TRIMPARAM_LEN];
    
    	/* 读取BMP280的参数 */
    	bmp280_read_len(BMP280_TRIMPARAM_FRG, param_buf, BMP280_TRIMPARAM_LEN);
    
    	/* 计算参数 */
    	bmp280_dev.calib_param.dig_T1 = (u16)((((u16)((u8)param_buf[1])) << 8) | param_buf[0]);
    	bmp280_dev.calib_param.dig_T2 = (s16)((((s16)((s8)param_buf[3])) << 8) | param_buf[2]);
    	bmp280_dev.calib_param.dig_T3 = (s16)((((s16)((s8)param_buf[5])) << 8) | param_buf[4]);
    	bmp280_dev.calib_param.dig_P1 = (u16)((((u16)((u8)param_buf[7])) << 8) | param_buf[6]);
    	bmp280_dev.calib_param.dig_P2 = (s16)((((s16)((s8)param_buf[9])) << 8) | param_buf[8]);
    	bmp280_dev.calib_param.dig_P3 = (s16)((((s16)((s8)param_buf[11])) << 8) | param_buf[10]);
    	bmp280_dev.calib_param.dig_P4 = (s16)((((s16)((s8)param_buf[13])) << 8) | param_buf[12]);
    	bmp280_dev.calib_param.dig_P5 = (s16)((((s16)((s8)param_buf[15])) << 8) | param_buf[14]);
    	bmp280_dev.calib_param.dig_P6 = (s16)((((s16)((s8)param_buf[17])) << 8) | param_buf[16]);
    	bmp280_dev.calib_param.dig_P7 = (s16)((((s16)((s8)param_buf[19])) << 8) | param_buf[18]);
    	bmp280_dev.calib_param.dig_P8 = (s16)((((s16)((s8)param_buf[21])) << 8) | param_buf[20]);
    	bmp280_dev.calib_param.dig_P9 = (s16)((((s16)((s8)param_buf[23])) << 8) | param_buf[22]);
    }
    
    //读取BMP280寄存器值
    //reg	: 要读取的寄存器地址
    //返回读取到的寄存器值
    unsigned char bmp280_read_reg(unsigned char reg)
    {
    	unsigned char reg_val;	  
    
    	/* BMP280在使用SPI接口的时候寄存器地址
    	 * 只有低7位有效,寄存器地址最高位是读/写标志位
    	 * 读的时候要为1,写的时候要为0。
    	 */
    	reg |= 0x80; 	
    	
       	BMP280_CSN(0);               			/* 使能SPI传输	 		*/
      	spi3ch0_readwrite_byte(reg);     		/* 发送寄存器地址  		*/ 
      	reg_val = spi3ch0_readwrite_byte(0XFF);	/* 读取寄存器的值 			*/
     	BMP280_CSN(1);                			/* 禁止SPI传输 			*/
      	return(reg_val);               	 		/* 返回读取到的寄存器值 */
    }	
    //读取BMP280连续多个寄存器
    //reg	: 要读取的寄存器地址
    //返回读取到的寄存器值
    
    void bmp280_read_len(unsigned char reg, unsigned char *buf, unsigned char len)
    {  
    	unsigned char i;
    
    	/* BMP280在使用SPI接口的时候寄存器地址
    	 * 只有低7位有效,寄存器地址最高位是读/写标志位
    	 * 读的时候要为1,写的时候要为0。
    	 */
    	reg |= 0x80; 
    	
       	BMP280_CSN(0);               			/* 使能SPI传输	 		*/
      	spi3ch0_readwrite_byte(reg);			/* 发送寄存器地址  		*/   	   
     	for(i = 0; i < len; i++)				/* 顺序读取寄存器的值 			*/
     	{
    		buf[i]=spi3ch0_readwrite_byte(0XFF);	
    	}
     	BMP280_CSN(1);                			/* 禁止SPI传输 			*/
    }	
    
    //写BMP280指定寄存器
    //reg	 : 要读取的寄存器地址
    //value: 要写入的值
    void bmp280_write_reg(unsigned char reg, unsigned char value)
    {
    	/* BMP280在使用SPI接口的时候寄存器地址
    	 * 只有低7位有效,寄存器地址最高位是读/写标志位
    	 * 读的时候要为1,写的时候要为0。
    	 */
    	reg &= ~0x80; 
    
       	BMP280_CSN(0);               			/* 使能SPI传输	 		*/
      	spi3ch0_readwrite_byte(reg);     		/* 发送寄存器地址  		*/ 
      	spi3ch0_readwrite_byte(value);			/* 发送要写入的值 			*/
     	BMP280_CSN(1);                			/* 禁止SPI传输 			*/
    }	
    
    //获取BMP280原始的温度数据值
    //返回原始的温度数据值
    signed int bmp280_get_uncomptemp(void)
    {
    	unsigned char temp_value[3];
    	signed int uncomp_temp = 0;
    	bmp280_read_len(BMP280_TEMPMSB_REG, temp_value, 3);
    	
    	uncomp_temp = (s32)((((u32)(temp_value[0])) << 12) 
    				| (((u32)(temp_value[1])) << 4)
    				| ((u32)temp_value[2] >> 4));
    	return uncomp_temp;
    }
    
    //获取BMP280原始的压力数据值
    //返回原始的温度数据值
    signed int bmp280_get_uncomppres(void)
    {
    	unsigned char pres_value[3];
    	signed int uncomp_pres = 0;
    
    	bmp280_read_len(BMP280_PRESMSB_REG, pres_value, 3);
    	
    	uncomp_pres = (s32)((((u32)(pres_value[0])) << 12) 
    				| (((u32)(pres_value[1])) << 4)
    				| ((u32)pres_value[2] >> 4));
    	return uncomp_pres;
    }
    
    //从BMP280的原始温度数据值计算出真实的温度数据值
    //uncomptemp	: 原始的温度数据值
    //返回得到的真实的数据值,这里将温度值扩大了100倍,比如5123 = 51.23°C。
    signed int bmp280_get_actualtemp(signed int uncomptemp)
    {
    	s32 v_x1_u32r = 0, v_x2_u32r = 0;
    	s32 temperature = 0;
    
    	/* 计算温度值,X1 */
    	v_x1_u32r = ((((uncomptemp >> 3) - ((s32)bmp280_dev.calib_param.dig_T1 << 1)))
    				* ((s32)bmp280_dev.calib_param.dig_T2)) >> 11;
    	
    	/* 计算温度值,X2 */
    	v_x2_u32r = (((((uncomptemp >> 4)- ((s32)bmp280_dev.calib_param.dig_T1))
    			   * ((uncomptemp >> 4) - ((s32)bmp280_dev.calib_param.dig_T1))) >> 12)
    			   * ((s32)bmp280_dev.calib_param.dig_T3))   >> 14;
    
    
    	/* 计算t_fine */
    	bmp280_dev.calib_param.t_fine = v_x1_u32r + v_x2_u32r;
    
    	/* 计算真实的温度值 */
    	temperature = (bmp280_dev.calib_param.t_fine * 5 + 128) >> 8;
    
    	return temperature;
    }
    
    //从BMP280的原始气压数据值计算出真实的气压数据值
    //uncomppres	: 原始的气压数据值
    //返回得到的真实的气压数据值,比如23658就是:
     *    					  23658Pa = 236.58hPa = 236.58 milllibar。
     */
    unsigned int bmp280_get_actualpres(s32 uncomppres)
    {
    	s32 v_x1_u32r = 0;
    	s32 v_x2_u32r = 0;
    	u32 v_pressure_u32 = 0;
    	
    	/* 计算X1 */
    	v_x1_u32r = (((s32)bmp280_dev.calib_param.t_fine) >> 1) - (s32)64000;
    	
    	/* 计算X2*/
    	v_x2_u32r = (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 11) * ((s32)bmp280_dev.calib_param.dig_P6);
    	v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((s32)bmp280_dev.calib_param.dig_P5)) << 1);
    	v_x2_u32r = (v_x2_u32r >> 2) + (((s32)bmp280_dev.calib_param.dig_P4) << 16);
    	
    	/* 计算X1*/
    	v_x1_u32r = (((bmp280_dev.calib_param.dig_P3 * (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 13)) >> 3)
    			 + ((((s32)bmp280_dev.calib_param.dig_P2) * v_x1_u32r) >> 1)) >> 18;
    	v_x1_u32r = ((((32768 + v_x1_u32r)) * ((s32)bmp280_dev.calib_param.dig_P1)) >> 15);
    	
    	/* 计算气压值 */
    	v_pressure_u32 = (((u32)(((s32)1048576) - uncomppres) - (v_x2_u32r >> 12))) * 3125;
    	
    	/* 检查溢出 */
    	if (v_pressure_u32 < 0x80000000)
    	{
    		if (v_x1_u32r != 0)
    			v_pressure_u32 = (v_pressure_u32 << 1) / ((u32)v_x1_u32r);
    		else
    			return BMP280_INVALID_DATA;
    	} else {
    
    		if (v_x1_u32r != 0)
    			v_pressure_u32 = (v_pressure_u32 / (u32)v_x1_u32r) * 2;
    		else
    			return BMP280_INVALID_DATA;
    	}
    
    	/* 计算X1 */
    	v_x1_u32r = (((s32)bmp280_dev.calib_param.dig_P9) * ((s32)(((v_pressure_u32 >> 3)
    			* (v_pressure_u32 >> 3)) >> 13))) >> 12;
    	
    	/* 计算X2*/
    	v_x2_u32r = (((s32)(v_pressure_u32 >> 2)) * ((s32)bmp280_dev.calib_param.dig_P8)) >> 13;
    	
    	/* 计算真实的气压值*/
    	v_pressure_u32 = (u32)((s32)v_pressure_u32 + ((v_x1_u32r + v_x2_u32r
    			+ bmp280_dev.calib_param.dig_P7) >> 4));
    	
    	return v_pressure_u32;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
  • 相关阅读:
    Vue3之uni-app中注册全局属性案例
    Coze+Discord:打造你的免费AI助手(教您如何免费使用GPT-4o/Gemini等最新最强的大模型/Discord如何正确连接Coze)
    笔记:电子设备接地,接的到底是什么地?
    InterSystems IRIS使用python pyodbc连接 windows环境,odbc驱动安装,DSN配置,数据源配置
    VR全景拍摄发展如何?在各行业应用中有优势吗?
    订单 延后自动关闭,五种方案优雅搞定!
    团队建设游戏大全
    简单记录下gin中使用中间件记录操作日志
    Mysql事务
    单片机KEIL C51堆栈地址分配原理,变量放RAM,small编译按data
  • 原文地址:https://blog.csdn.net/qq_61540355/article/details/126693988