Funpack第六期-使用max32660实现智能手表
硬件基于max32660, 软件基于rt-thread实现智能手表
标签
Funpack第六期
MAX32660-EVSYS
rt-thread
lvgl
霍尔传感器
james
更新2021-04-01
1030
1 实现功能介绍

这回根据硬禾的活动要求, 实现了带有传感器的智能手表. 手表的系 统使用rt-thread, 可以扩展功能, 可以多个线程运行处理后台传感 器数据.

手表的显示部分使用240x240圆形彩色屏幕, 使用lvgl图形库驱动, 可以显示数字时间和模拟指针时间(解决spimsss bug后实现). 可以 换表盘背景(解决spi1 bug后实现). 使用MAX32660的RTC外设计时.

传感器使用A3144, 霍尔传感器, 输出一位开关量. 该传感器用于手 表控制屏幕背光. 以达到省电和适配使用场景的目的.

2 主要代码片段
  1. lvgl移植回调函数

此回调函数用于lvgl局部刷新, lvgl只使用了10*每行点数*16bit的 数据完成了显示更新. 在画控件的时候进行了优化, 充分利用mask使 其可以运行在小ram的环境中.

static void lcd_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
    int x1, x2, y1, y2;

    x1 = area->x1;
    x2 = area->x2;
    y1 = area->y1;
    y2 = area->y2;

    int32_t len = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2;

    LOG_D("%d, %d, %d, %d\n", x1, y1, x2, y2);

    LCD_Address_Set(x1,y1,x2,y2);

    LCD_WR_N_DATA(color_p, len);

    lv_disp_flush_ready(disp_drv);
}
void LCD_WR_N_DATA(void *dat, int len) {
  rt_spi_send(spi_lcd_dev, dat, len);
}
void LCD_Writ_Bus(u8t dat) 
{   
  rt_spi_send(spi_lcd_dev, &dat, 1);
}
  1. rt-thread spi设备初始化
int lcd_spi_init(void) {
  // attach
  rt_hw_spi_device_attach("spi0", "spi00", 7);

  // find
  spi_lcd_dev = (struct rt_spi_device *)rt_device_find("spi00");

  RT_ASSERT(spi_lcd_dev != RT_NULL);

  // configure
  struct rt_spi_configuration cfg;
  cfg.data_width = 8;
  cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
  cfg.max_hz = 2 * 1000 * 1000;                           /* 4M */

  rt_spi_configure(spi_lcd_dev, &cfg);

  rt_kprintf("spi_lcd_init ok");

  return RT_EOK;
}
  1. lvgl控件的简单使用方法
lv_obj_t * btn2;
lv_obj_t * label;
void p_ui_init(void)
{
    lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(btn1, event_handler);
    lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, -40);

    label = lv_label_create(btn1, NULL);
    lv_label_set_text(label, "Time");

    btn2 = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(btn2, event_handler);
    lv_obj_align(btn2, NULL, LV_ALIGN_CENTER, 0, 40);
    lv_btn_set_checkable(btn2, true);
    lv_btn_toggle(btn2);
    lv_btn_set_fit2(btn2, LV_FIT_NONE, LV_FIT_TIGHT);

    label = lv_label_create(btn2, NULL);
    lv_label_set_text(label, "Toggled");
}
  1. 解决sdk中的spimss驱动bug(还在测试)

spi1(spimss)接收数据必须在发送数据的时候, 因为他们复用同一个 shift register, master和slave形成了一个circular buffer. 这种 情况下如何实现rtspisendthenrecv(两个ops->xfer, 先发后收).

diff --git a/bsp/maxim/libraries/MAX32660PeriphDriver/Source/spimss.c b/bsp/maxim/libraries/MAX32660PeriphDriver/Source/spimss.c
index 6dfa2be36..8c0851246 100644
--- a/bsp/maxim/libraries/MAX32660PeriphDriver/Source/spimss.c
+++ b/bsp/maxim/libraries/MAX32660PeriphDriver/Source/spimss.c
@@ -253,7 +253,8 @@ int SPIMSS_MasterTrans(mxc_spimss_regs_t *spi, spimss_req_t *req)

     spi->mod &= ~(MXC_F_SPIMSS_MOD_SSV);  // This will assert the Slave Select.
     spi->ctrl |= MXC_F_SPIMSS_CTRL_SPIEN;  // Enable/Start SPI
-
+
+    // kick off
     while (SPIMSS_MasterTransHandler(spi,req)!=0) {
     }

@@ -387,14 +388,21 @@ uint32_t SPIMSS_TransHandler(mxc_spimss_regs_t *spi, spimss_req_t *req)

         if (remain) {
             if (remain > MXC_SPIMSS_FIFO_DEPTH) {
-                spi->dma = ((spi->dma & ~MXC_F_SPIMSS_DMA_RX_FIFO_CNT) | ((2) << MXC_F_SPIMSS_DMA_RX_FIFO_CNT_POS));
+                spi->dma = ((spi->dma & ~MXC_F_SPIMSS_DMA_RX_FIFO_CNT) | ((MXC_SPIMSS_FIFO_DEPTH) << MXC_F_SPIMSS_DMA_RX_FIFO_CNT_POS));
             } else {
-                spi->dma = ((spi->dma & ~MXC_F_SPIMSS_DMA_RX_FIFO_CNT) | ((remain-1) << MXC_F_SPIMSS_DMA_RX_FIFO_CNT_POS));
+                spi->dma = ((spi->dma & ~MXC_F_SPIMSS_DMA_RX_FIFO_CNT) | ((remain) << MXC_F_SPIMSS_DMA_RX_FIFO_CNT_POS));
             }

             int_en = 1;
         }

+        // pump
+        if (req->tx_data == NULL && remain > 0) {
+          for (int i = 0; i < remain; ++i) {
+            spi->data8[0] = 0;
+          }
+        }
+
         // Break out if we've received all the bytes and we're not transmitting
         if ((req->tx_data == NULL) && (req->rx_num == length)) {
             spi->ctrl &= ~(MXC_F_SPIMSS_CTRL_IRQE | MXC_F_SPIMSS_CTRL_STR);
3 心得体会和建议
  1. rt-thread很好用, package, 支持的bsp多, 开箱即用.
  2. 为了调试和swd复用pin的外设, 搞坏了两个烧录器, 如果可以, 不去碰默认是调试甚至reset功能的pin, 如果可以, 多买几个烧 录器备用.
  3. 本期想用python+github大法, 奈何板上flash空间太小, micropython只跑起来试了试, 没程序的空间了.
团队介绍
james
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号