[原创] SAM4E LED0亮度随光照自动调节(TWI读bh1750)

梭罗瓦尔登   2015-2-28 13:32 楼主
现在的智能手机其实都带光强传感器,大体是这样的,在光照强的地方,屏幕也亮,因此有利于看清楚屏幕上的字,之前发过呼吸灯的例子,这里我再加上BH1750来模拟智能手机的这项功能,只是做个小demo,也有很多不好的地方,大哥们就多指正 ,我利用ASF里的TWI例程加以修改,使之能够读出BH1750传感器的数据并转换成光强强度,然后根据光强设置PWM的占空比,来设置一下亮度,原理就是这样。 贴一下代码,注释都在代码里,有问题及时回帖交流,不完善的及时指正。
  1. THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED

  2. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  3. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  4. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  5. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  6. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  7. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  8. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  9. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  10. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  11. * POSSIBILITY OF SUCH DAMAGE.
  12. *
  13. *
  14. */
  15. #include //******************************************** 20150127修改*********************************************//
  16. #include
  17. #include "conf_board.h"
  18. //****************************************
  19. uint32_t light=0;
  20. #define PERIOD_VALUE 547
  21. #define BREATH_INTERVAL_PERIOD 100 /*LED暗下来一段时间*/
  22. #define STRING_EOL "\r"
  23. #define STRING_HEADER "-- EDBG TWI Information Interface Example --\r\n" \
  24. "-- "BOARD_NAME" --\r\n" \
  25. "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
  26. /** TWI Bus Clock 400kHz */
  27. #define TWI_CLK 400000
  28. /** EDBG TWI interface address */
  29. #define EDBG_ADDRESS 0xD1;
  30. /** Request token of EDBG TWI information interface */
  31. #define EDBG_EXTEN_BOARDS_TOKEN 0x75;
  32. #define EDBG_KIT_DATA_TOKEN 0xD2;
  33. #define BH1750 0x5C
  34. /** I2C related structure */
  35. twi_options_t opt;
  36. twi_packet_t packet_rx;
  37. twi_packet_t packet_tx;
  38. /* Number of times to try to send packet if failed. */
  39. #define TIMEOUT 10
  40. /** Read buffer */
  41. uint8_t read_buffer[1];
  42. /** Extension board info structure*/
  43. uint8_t extension_map[2];
  44. uint8_t extension_info[64];
  45. uint16_t minimum_voltage;
  46. uint16_t maximum_voltage;
  47. uint16_t minimum_current;
  48. #ifdef CONF_KIT_DATA_EXIST
  49. /** Kit data structure*/
  50. uint8_t kit_data[256];
  51. #endif
  52. /**
  53. * \brief Function for show the extension boards information
  54. *
  55. */
  56. /*[中断处理程序]*/
  57. void PWM_Handler(void)
  58. {
  59. static uint32_t ul_duty = 0; /* PWM 占空比*/
  60. static uint8_t fade_in = 1; /* LED 淡入标志 */
  61. static uint8_t dark_period = 0; /* LED 完全暗下来时间 */
  62. /* 读取PWM_ISR1寄存器,同时可以拉低中断 */
  63. uint32_t events = PWM->PWM_ISR1;
  64. /* 先确定是否是指定的中断,PWM_ISR1_CHID2表示PWM_ISR1寄存器的CHID0位*/
  65. if ((events & PWM_ISR1_CHID2) != 0)
  66. {
  67. if (dark_period != 0)
  68. {
  69. dark_period--;
  70. return;
  71. }
  72. /* 设置新的占空比 */
  73. PWM->PWM_CH_NUM[2].PWM_CDTYUPD = PWM_CDTY_CDTY(light/100);
  74. }
  75. }
  76. void ConfigPIO(void)
  77. {
  78. /* 引脚由外设控制 */
  79. PIOD->PIO_PDR = PIO_PD22;
  80. /* 选择外设 */
  81. /* PIOD选择外设D(将影响PD所有引脚) */
  82. PIOD->PIO_ABCDSR[0] = 0;
  83. PIOD->PIO_ABCDSR[1] = 0;
  84. }
  85. /*配置PWM*/
  86. void ConfigPWM(void)
  87. {
  88. /* 外设时钟启用,PWM的ID大于31,需要在PMC_PCER1中启用*/
  89. PMC->PMC_PCER1 = 1 << (ID_PWM - 32);
  90. /* 禁用通道2,以进行配置 */
  91. PWM->PWM_DIS = PWM_DIS_CHID2;
  92. /* 配置通道2,计数器时钟选择为32分频,周期左对齐,先输出低电平,不使用死区发生器。
  93. 这里需要用到较高频率的时钟,所以选择使用主时钟经32分频后的时钟(12.5 kHz)。计数器周期为400,即输出脉冲频率为125000/400 = 312.5 Hz。*/
  94. PWM->PWM_CH_NUM[2].PWM_CMR =PWM_CMR_CPRE_MCK_DIV_32;
  95. /* 启用中断 */
  96. PWM->PWM_IER1 = PWM_IER1_CHID2;
  97. PWM->PWM_CH_NUM[2].PWM_CPRD = PWM_CPRD_CPRD(PERIOD_VALUE); /* 设置周期 */
  98. PWM->PWM_CH_NUM[2].PWM_CDTY = PWM_CDTY_CDTY(0); /* 设置占空比*/
  99. /* 使能中断 */
  100. NVIC_ClearPendingIRQ(PWM_IRQn);
  101. NVIC_SetPriority(PWM_IRQn, 0);
  102. NVIC_EnableIRQ(PWM_IRQn);
  103. /* 使能 PWM */
  104. PWM->PWM_ENA = PWM_ENA_CHID2;
  105. }
  106. static void show_extension_boards_information(void)
  107. {
  108. //uint8_t request_token = EDBG_EXTEN_BOARDS_TOKEN;
  109. uint32_t timeout = 0;
  110. uint8_t board_num = 0;
  111. uint8_t i;
  112. uint8_t request_token[5] ={0x01,0x10,0,0,0};//地址意义看上面的宏定义
  113. uint8_t dat[2]={0x01,0x10}; //初始值
  114. for(i=0;i<2;i++)
  115. { packet_tx.chip = BH1750;
  116. packet_tx.addr_length = 1;
  117. packet_tx.addr[0] = request_token[i];
  118. packet_tx.buffer = dat+i;
  119. packet_tx.length = 1;
  120. while (twi_master_write(EDBG_I2C_MODULE, &packet_tx) != TWI_SUCCESS) {
  121. /* Increment timeout counter and check if timed out. */
  122. if (timeout++ == TIMEOUT) {
  123. puts("timeout!\n");
  124. return;
  125. }
  126. }
  127. }
  128. return;
  129. }
  130. #ifdef CONF_KIT_DATA_EXIST
  131. /*
  132. uint32_t GetData(uint8_t* REG_Address)
  133. {
  134. uint8_t H,L;
  135. H=*REG_Address;
  136. L=*(REG_Address+1);
  137. return (H<<8)+L; //合成数据
  138. }
  139. */
  140. static void bh1750_init(void)
  141. {
  142. uint8_t dat[2]={0x01,0x11}; //command 0x01 power on 0x10 start converting
  143. uint8_t timeout=0;
  144. uint8_t send_count;
  145. for(send_count=0;send_count<=1;send_count++)//这里要看BH1750的数据手册,它把第二个字节的数据当命令,所以我们先发俩字节来初始化它
  146. {
  147. packet_tx.chip = BH1750;
  148. packet_tx.buffer = dat+send_count;
  149. packet_tx.length = 1;
  150. while (twi_master_write(EDBG_I2C_MODULE, &packet_tx) != TWI_SUCCESS) {
  151. // Increment timeout counter and check if timed out.
  152. if (timeout++ == TIMEOUT) {
  153. puts("timeout!!!!!!!!!!!\n");
  154. return;
  155. }
  156. }
  157. delay_ms(10);
  158. }
  159. }
  160. static void show_light_data(uint32_t *light)
  161. {
  162. uint8_t g_data[6]={0x00,0x00};
  163. uint8_t timeout=0;
  164. uint32_t g_data_32[3]={0x00,0x00};
  165. float lux;
  166. packet_rx.chip = BH1750;
  167. packet_rx.addr_length = 1;
  168. packet_rx.addr[0] = 0x23;//数据从0x23读出
  169. packet_rx.buffer =g_data;
  170. packet_rx.length = 2;//要读两个字节
  171. while (twi_master_read(EDBG_I2C_MODULE, &packet_rx) != TWI_SUCCESS) {
  172. /* Increment timeout counter and check if timed out. */
  173. if (timeout++ == TIMEOUT) {
  174. printf("\read error \n");
  175. return;
  176. }
  177. }
  178. g_data_32[0]=(g_data[0]<<8)+g_data[1];//data processing
  179. lux=(float)g_data_32[0]/1.2;
  180. /** show kit data */
  181. printf("\rLIGHT == %d \n LUX == %d \n",g_data_32[0],(uint)lux);//串口打印光强数据
  182. *light=(uint32_t)lux;//数据传出去,来调节PWM从而控制led0的亮度
  183. }
  184. #endif
  185. /**
  186. * \brief Function for configuring I2C master module
  187. *
  188. * This function will configure the I2C master module with
  189. * the SERCOM module to be used and pinmux settings
  190. */
  191. static void configure_i2c_master(void)
  192. {
  193. /* Enable the peripheral clock for TWI */
  194. pmc_enable_periph_clk(EDBG_I2C_MODULE_ID);
  195. /* Configure the options of TWI driver */
  196. opt.master_clk = sysclk_get_cpu_hz();
  197. opt.speed = TWI_CLK;
  198. if (twi_master_init(EDBG_I2C_MODULE, &opt) != TWI_SUCCESS) {
  199. puts("-E-\tTWI master initialization failed.\r");
  200. while (1) {
  201. /* Capture error */
  202. }
  203. }
  204. }
  205. static void configure_console(void)
  206. {
  207. const usart_serial_options_t uart_serial_options = {
  208. .baudrate = CONF_UART_BAUDRATE,
  209. .paritytype = CONF_UART_PARITY
  210. };
  211. /* Configure console UART. */
  212. sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
  213. stdio_serial_init(CONF_UART, &uart_serial_options);
  214. }
  215. /**
  216. * \brief Main application
  217. */
  218. int main(void)
  219. {
  220. /* Initialize the SAM system */
  221. sysclk_init();
  222. /* Initialize the board */
  223. board_init();
  224. /*Configure UART console.*/
  225. configure_console();
  226. /* Configure the I2C master module */
  227. configure_i2c_master();
  228. /* Output example information */
  229. puts(STRING_HEADER);
  230. /* Show the extension boards information */
  231. WDT->WDT_MR = WDT_MR_WDDIS;
  232. ConfigPWM();
  233. ConfigPIO();
  234. //while (1);
  235. while(1)
  236. {
  237. #ifdef CONF_KIT_DATA_EXIST
  238. bh1750_init();//初始化之后一定要等120ms
  239. delay_ms(120);
  240. show_light_data(&light);
  241. #endif
  242. }
  243. while (1)
  244. {}
  245. }

本帖最后由 梭罗瓦尔登 于 2015-2-28 13:40 编辑
  • addr.png
  • bh1750command.png
  • 效果.png

    led0.zip (2015-2-28 13:31 上传)

    4.21 MB, 阅读权限: 5, 下载次数: 2

    打开即可食用

回复评论 (2)

谢谢大神
点赞  2018-3-30 16:47
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复