这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 转脑袋的灯——调试LSM303与pwm三通道以及手机app控制

共1条 1/1 1 跳转至

转脑袋的灯——调试LSM303与pwm三通道以及手机app控制

菜鸟
2018-09-18 14:48:06     打赏

上次用stm32cubemx生成了L053R8的一些基础程序,现在就来进行一些改动和添加,那么改动的程序应该添加到哪里呢,大家看一下生成的函数,发现有这个注释:

  /* USER CODE BEGIN 1 */

 

  /* USER CODE END 1 */

类似于这种的,有BEGIN和END的,把要添加的函数放在这中间,这样的话,假如想重新配置cubemx,那么重新生成的函数就不会覆盖把它覆盖掉。

当然了首先需要配置一下串口的printf,这个就不用多说了,找到usart.c文件添加这个函数:

#ifdef __GNUC__

  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf

     set to 'Yes') calls __io_putchar() */

  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */

/**

  * @brief  Retargets the C library printf function to the USART.

  * @param  None

  * @retval None

  */

PUTCHAR_PROTOTYPE

{

  /* Place your implementation of fputc here */

  /* e.g. write a character to the USART2 and Loop until the end of transmission */

  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

 

  return ch;

}

当然了,也并不仅仅局限于这种,还有很多种,无非就是重定向罢了,然后在h文件里声明一下,这时回到main函数,再写个printf函数用串口直接就可以打印了,所以说用cubemx很方便的。

既然串口配置完了,那么接下来要做的就是iic的修改了,在官方给的例程当中,只需要修改它的初始化数据和iic读取以及写入,那么来看看官方的例程:

//************初始化L3G4200D的加速度*********************************

void LSM303A_Init( void )

{

   

  I2C_WriteOneByte(I2C1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG1, 0x37);

  I2C_WriteOneByte(I2C1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4, 0x00);

}

//************初始化L3G4200D的磁感应*********************************

 

void LSM303M_Init( void )

{

 

I2C_WriteOneByte(I2C1,LSM303M_I2C_ADDR,LSM303M_CRB_REG, 0xa0);


I2C_WriteOneByte(I2C1,LSM303M_I2C_ADDR,LSM303M_MR_REG, 0x00);

}

 

 

   楼主找了一下HAL库里面,没有这个函数,那么需要替换掉,进入到HAL的iic库中,可以看到这个函数:

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

对,就是这个,不过可能有人疑惑了,怎么有7个形参?官方里面只有四个啊,对此不用太在意,可以看一下上面的注释,翻译一下会发现有几个没什么用,楼主就不一样样详解了,直接改动代码:

//************初始化L3G4200D的加速度*********************************

void LSM303A_Init( void )

{

  uint8_t data;

data = 0x37;

  HAL_I2C_Mem_Write(&hi2c1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG1,1,&data,1,35);

data = 0x00;

  HAL_I2C_Mem_Write(&hi2c1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4,1,&data,1,35);

}

//************初始化L3G4200D的磁感应*********************************

 

void LSM303M_Init( void )

{

  uint8_t data;

data = 0xa0;

HAL_I2C_Mem_Write(&hi2c1,LSM303M_I2C_ADDR,LSM303M_CRB_REG,1, &data,1,35);

data = 0x00;

HAL_I2C_Mem_Write(&hi2c1,LSM303M_I2C_ADDR,LSM303M_MR_REG,1, &data,1,35);

}

 

 

这个就是改动之后的write函数,但是iic可不止write,还有read呢,看一下官方的read函数,由于是分开的,楼主给它们合在了一起:

I2C_Read(I2C1,LSM303M_I2C_ADDR,LSM303M_OUT_X_H,buffer,6);//|0x80

I2C_Read(I2C1,LSM303M_I2C_ADDR,LSM303M_CRB_REG,&f,1);

 

I2C_Read(I2C1,LSM303A_I2C_ADDR,LSM303A_OUT_X_L|0x80,buffer,6);

I2C_Read(I2C1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4|0x80,ctrlx,2);

 

  I2C_Read(I2C1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4,ctrlx,2);

 

Ok,综合起来就是上面五个,同样的,HAL库里面没有这个函数,老样子,

在iic库里面,找到这个函数:

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

  其实就在write的下面而已,改动一下:

HAL_I2C_Mem_Read(&hi2c1,LSM303M_I2C_ADDR,LSM303M_OUT_X_H,1,buffer,6,35);//|0x80

HAL_I2C_Mem_Read(&hi2c1,LSM303M_I2C_ADDR,LSM303M_CRB_REG,1,&f,1,35);

 

HAL_I2C_Mem_Read(&hi2c1,LSM303A_I2C_ADDR,LSM303A_OUT_X_L|0x80,1,buffer,6,35);

HAL_I2C_Mem_Read(&hi2c1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4|0x80,1,ctrlx,2,35);

 

HAL_I2C_Mem_Read(&hi2c1,LSM303A_I2C_ADDR,LSM303A_CTRL_REG4,1,ctrlx,2,35);

 

至此,关于LSM303iic的协议改动完成了,回到主函数,官方里面有这个代码:

     float buf_A[3],buf_M[3];

float north,first_north;

char flag;

uint16_t n = 100;

 

void Delay(uint32_t nCount)

{

  for(; nCount != 0; nCount--);

}

 

void Date_AM()

{

     LAM303M_Raed(buf_M);

     LAM303A_Raed(buf_A);

     north=Data_conversion(buf_A,buf_M);      

     printf("X_A=%f m/s^2\r\n",buf_A[0]);

     printf("Y_A=%f m/s^2\r\n",buf_A[1]);

     printf("Z_A=%f m/s^2\r\n",buf_A[2]);

 

     printf("X_M=%f T\r\n",buf_M[0] );

     printf("Y_M=%f T\r\n",buf_M[1]);

     printf("Z_M=%f T\r\n",buf_M[2]);

     printf("north=%f degree \r\n",north);

     printf("\r\n");

}

至此,用串口就可以打印出所有的数据了。

  其实最开始的时候,楼主没有打算用电子罗盘LSM303(因为当时没买),当时手上有一个MPU6050,是原来参加电赛留下来的东西,用F103的板子,也弄出了旋转改变亮度的效果,但是算法相当复杂,用到了DMP四元数和角速度积分以及欧拉角的算法(毕竟MPU6050大多时候用来测翻滚角和俯仰角的,用来测旋转角度也就是偏航角那么算法就更加复杂,)后来在移植到L053的板子上时出现了困难,因为初次接触HAL库,很多地方完全不了解,所以最后迫不得已还是买了电子罗盘,不过电子罗盘就简单多了,毕竟它的老本行就是测角度,没有复杂的算法。

 

 至此,电子罗盘的部分算是完成了,下一步,就是那个pwm灯了。

打开tim.c那个文件夹,cubemx已经把所有的配置都写好了。在最下面添加一段代码:

void USER_PWM_SetDutyRatio(TIM_HandleTypeDef *htim,uint32_t Channel,uint8_t value)

{

  TIM_OC_InitTypeDef sConfigOC;

 

  uint32_t period=htim->Init.Period+1;

  uint32_t pluse=(value * period)/100;

 

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = pluse;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, Channel);

  HAL_TIM_PWM_Start(htim, Channel);  

}

其中第一个形参代表定时器型号,第二个则是定时器通道,第三个是占空比,满值是100。然后在tim.h文件里声明一下这个函数,可以在main函数的while循环里面添加这个函数,例如:

USER_PWM_SetDutyRatio(&htim2,TIM_CHANNEL_2,n);

然后将RGB全彩灯盘连上对应的引脚就可以观察到亮度变化,当然了,前提是设定一个占空比,后期这个占空比可以通过电子罗盘的数据变化来变化,只要数值赋值给一个变量就是了。

 对于这个部分。楼主也是上传了视频,都是用这个教程里的方法来写的。大家可以看看。

视频链接:

http://v.youku.com/v_show/id_XMzgyMjExMzE2OA==.html?spm=a2h0j.11185381.listitem_page1.5!5~A

 

  到此,代码部分已经讲解完毕了,大家可以根据这个代码好好看看,至于代码里面注释的部分是后期用手机app控制的通信协议部分

(图片上就是app 的界面图)

image.png

如果对app控制感兴趣的人比较多,楼主可以考虑放出教程。

给大家看看实物图,手机像素不高,大家见谅一下。

大家也看到了。电源就是一个硕大的充电宝,不过挺好用,电量充足。下面那个则是传说中的秘密武器了——旋转灯座,可以转动它来改变亮度,

可能有人会问了,充电宝对面的那两个模块是什么?那个绿色的是扩展的VCC GND 接口。而那个黑色的则是后期添加的东西,一个ESP8266的模块,里面有通信协议,就是通过它来进行手机软件控制的,看起来很高大上的样子,当然了。老样子,大家可以看看演示视频,有app控制灯的颜色的说明。

   演示视频链接:

   http://v.youku.com/v_show/id_XMzgyMjExMzQ2OA==.html?spm=a2h0j.11185381.listitem_page1.5!6~A

   最后,希望每一个人都能做出来旋转灯,甚至是智能旋转灯!!

     最终程序:LSM3031.rar

         资料:STM32L053电路图.rar

image.pngimage.png




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]