打印
[其他ST产品]

STM32G031无线温湿度仪开源项目 -3MCU的初始化

[复制链接]
137|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1,修改代码的地方
上一章讲到了应用CubeMX产生了项目源文件,现在用CubeIDE打开,我们会看到很多:
/* USER CODE BEGIN 1*/
/* USER CODE END 1*/
就是说,你的代码要放在这些标记的中间,如果我们返回去CubeMX修改了配置,重新生成了代码,但是放在这些标记中间的代码是不会被修改的。
另外,对于自动产生的代码,尽量不要修改。



使用特权

评论回复
沙发
梅花香自123|  楼主 | 2023-5-30 17:45 | 只看该作者
2,MCU本身的初始化
这里主要包括时钟、IO口、Timer、串口等的初始化
其中MX_IWDG_Init() 是独立看门狗的初始化,这个先把它注掉,不然不好调试
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  //MX_IWDG_Init();
  MX_RTC_Init();

使用特权

评论回复
板凳
梅花香自123|  楼主 | 2023-5-30 17:45 | 只看该作者
3,MCU初始化,读写内部FLASH,写自定义配置
STM32G031C8单片机内部都有很大的内部FLASH空间,我们可以拿出一点来作为自定义的配置空间,这样就不需要额外的EEPROM,但是内部FLASH的稳定性及读写速度、读写便利性不如EEPROM,一般运行过程中,不频繁读写FLASH还是没问题的。
这是写自定义配置的入口:

  /* USER CODE BEGIN 2 */

  //---1, MCU CONFIGURE ------------
  thisMCU_init();

使用特权

评论回复
地板
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者
进去看一下:
这里是读FLASH的程序:这里是从baseFlashAdd31地址开始,读40个字节
baseFlashAdd31=0x0800F800,即最后一个2K的程序空间作为自定义空间,因为FLASH是整块擦除的,所以最好定义整块空间。

//-----------------------------
void  dtkReadConfigure(void)
{
        dtkReadFlash(baseFlashAdd31, 40);
}

使用特权

评论回复
5
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者
//-----------------------------
void  dtkReadFlash(uint32_t  startAdd,  uint16_t countToRead)
{
        __IO uint32_t   data32 = 0;
        uint8_t         i=0;
        uint32_t        tempAdd=0;

        tempAdd = startAdd;
        for(i=0; i<countToRead; i=i+4)
        {

                data32 = *(__IO uint32_t *)tempAdd;
                //startAdd= startAdd+4;

                dtkReadedConfig[i] = (data32>>24) & 0x000000FF;
                dtkReadedConfig[i+1] = (data32>>16) & 0x000000FF;
                dtkReadedConfig[i+2] = (data32>>8) & 0x000000FF;
                dtkReadedConfig[i+3] = data32 & 0x000000FF;

                tempAdd = tempAdd +4;
        }
}

使用特权

评论回复
6
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者
//-----扇区 32 -------------------------
#define    baseFlashAdd31    0x0800F800

使用特权

评论回复
7
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者

使用特权

评论回复
8
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者
下面是写FLASH的程序:

void  dtkWriteConfigure(void)
{
        dtkWriteFlash(baseFlashAdd31, dtkWritedConfig, 40);
}

使用特权

评论回复
9
梅花香自123|  楼主 | 2023-5-30 17:46 | 只看该作者
/* -----------------------------------------------------------------
*  startAdd: 必须为某一页的起始地址:baseFlashAdd60 -baseFlashAdd63
*  countToWrite必须为8的倍数(即一次写入为Two Word的倍数)
*
*  ----------------------------------------------------------------*/
void  dtkWriteFlash(uint32_t  startAdd,  uint8_t  *writeData,  uint16_t countToWrite)
{
        uint32_t    i=0;
        uint64_t    tempWriteData;
        uint32_t    tempWriteAdd;
        HAL_StatusTypeDef  status;

        uint32_t     tempW1=0;
        uint32_t     tempW2=0;

    HAL_FLASH_Unlock();
    //HAL_FLASH_Unlock();

    FLASH_EraseInitTypeDef f;
    f.TypeErase = FLASH_TYPEERASE_PAGES;
    f.Page = 31;  //--只读写Page31的内容(即最后一个Page,2K字节
    f.NbPages = 1;


    uint32_t PageError = 0;

    HAL_FLASHEx_Erase(&f, &PageError);

        for(i=0; i<countToWrite ; i=i+8)
    {
          tempW1=0;
          tempW2=0;
          tempWriteData=0;

          tempW1 = writeData[i];
          tempW1 = tempW1<<8;
          tempW1 = tempW1 | writeData[i+1];

          tempW1 = tempW1<<8;
          tempW1 = tempW1 | writeData[i+2];

          tempW1 = tempW1<<8;
          tempW1 = tempW1 | writeData[i+3];


          tempW2 = writeData[i+4];
          tempW2 = tempW2<<8;
          tempW2 = tempW2 | writeData[i+5];

          tempW2 = tempW2<<8;
          tempW2 = tempW2 | writeData[i+6];

          tempW2 = tempW2<<8;
          tempW2 = tempW2 | writeData[i+7];

          tempWriteData = tempWriteData|tempW2;
          tempWriteData = tempWriteData<<32;
          tempWriteData = tempWriteData | tempW1;

          tempWriteAdd = startAdd + i;

          //HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, tempWriteAdd, tempWriteData);
          HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, tempWriteAdd, tempWriteData);

      // Wait for last operation to be completed
      status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

      // If the program operation is completed, disable the PG Bit
      CLEAR_BIT(FLASH->CR, FLASH_CR_PG);

      // In case of error, stop programation procedure
      if (status != HAL_OK)
      {
        break;
      }

    }
}

使用特权

评论回复
10
梅花香自123|  楼主 | 2023-5-30 17:47 | 只看该作者
在本项目中,我们开辟了40个字节的自定义配置,其中第一个字节表示配置是否写过了,如果是0xA5,表示配置已经写过了,第二个字节是ModBus地址,默认写入0xF0,最后一个字节是前面39个字节的和保留低8位(和校验),如果校验不通过,则重写FLASH。
其它的字节没有用到。
//--------------
void  thisMCU_init(void)
{
        uint8_t   tempXY=0;

        dtkReadConfigure();

        switch(is_dtkConfigured(dtkReadedConfig, 40))
         {
                case 0:   //not Configured
                        dtkWritedConfig[0] = 0xA5;    //--是否配置 标志
                        dtkWritedConfig[1] = 0xF0;    //--默认的ModBus地址

                        tempXY = getXY(dtkWritedConfig,40);
                        dtkWritedConfig[39] = tempXY;

                        dtkWriteConfigure();
                        break;

                case 1:  //configured, but error
                        dtkWritedConfig[0] = 0xA5;    //--是否配置 标志
                        dtkWritedConfig[1] = 0xF0;    //--默认的ModBus地址

                        tempXY = getXY(dtkWritedConfig,40);
                        dtkWritedConfig[39] = tempXY;

                        dtkWriteConfigure();
                        break;

                case 2:  //configured, right
                        dtkModbusAdd = dtkReadedConfig[1];
                        drf1609h_status=0;
                        //newEventStart(EVENT_1,  2000);   //--Wait DRF1609H Started - 2S
                        //newEventStart(EVENT_4, 800);    //--WatchDog refresh
                        break;
         }

        readDataReportModel();
}

使用特权

评论回复
11
梅花香自123|  楼主 | 2023-5-30 17:48 | 只看该作者
4,MCU初始化,读取本项目运行模式
主要是读取IO口S1,S2的状态,组合成有4种运行模式:就是分别将DRF1609H设置为Router或End Device,主动上报数据或等待ModBus指令上报数据,其中如果将DRF1609H设置成End Device,同时是自动上报数据,则自动进入低功耗上报数据状态。

#define   EndDeviceLowPower         1
#define   EndDeviceWaitModbus       2
#define   RouterActiveReport        3
#define   RouterWaitModbus          4

使用特权

评论回复
12
梅花香自123|  楼主 | 2023-5-30 17:48 | 只看该作者
//--------------
void  readDataReportModel(void)
{
        uint8_t   val1=0, val2=0;

        val1 = HAL_GPIO_ReadPin(GPIOB, S1_Pin);
        val2 = HAL_GPIO_ReadPin(GPIOB, S2_Pin);

        //---------
        if( (val1==0) & (val2==0) )
        {
                sysRuningModel = EndDeviceLowPower;
        }

        //---------
        if( (val1==0) & (val2==1) )
        {
                sysRuningModel = EndDeviceWaitModbus;
        }


        //---------
        if( (val1==1) & (val2==0) )
        {
                sysRuningModel = RouterActiveReport;
        }

        //---------
        if( (val1==1) & (val2==1) )
        {
                sysRuningModel = RouterWaitModbus;
        }


        //---------------  ----------------
        if(val2 ==1)
        {
                dataReportModel = waitModBus;
        }
        else
        {
                dataReportModel = activeReport;
        }

}

使用特权

评论回复
13
梅花香自123|  楼主 | 2023-5-30 17:48 | 只看该作者
5,LED灯的初始化
本项目中用了2个LED,LED1周期性的闪,用来指示软件是否正常运行,LED2用来指示DRF160H是否加入网络及数据的收发。
LED的闪,我们用到了Timer3的中断,在Timer3的中断里计时,控制LED的闪、灭时间,首先在time.c文件里加上Timer3的中断函数:
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim3.Instance)   //---Timer3 中断入口 ---------
    {
            LED1_FLASH();
            LED2_FLASH();

            newEventCount();

            HAL_UART_ReceivedCount();

            //HAL_I2C_ReceivedCount();
    }
}

/* USER CODE END 1 */

使用特权

评论回复
14
梅花香自123|  楼主 | 2023-5-30 17:49 | 只看该作者
即每次timer3中断后,都会执行下LED1_FLASH(),再进去里面看看:原来是控制LED1闪的速度。

使用特权

评论回复
15
梅花香自123|  楼主 | 2023-5-30 17:49 | 只看该作者
//---------------------------
void LED1_FLASH(void)
{
        LED1_FLASH_count++;

        switch (LED1_status)
        {
                case LED_FLASH_quick:
                        if(LED1_FLASH_count <= LED1_S1)
                        {
                                LED1_ON();
                        }
                        if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S2) )
                        {
                                LED1_OFF();
                        }
                        if ( LED1_FLASH_count > LED1_S2 )
                        {
                                LED1_FLASH_count =0;
                                LED1_ON();
                        }
                        break;

                case LED_FLASH_medium:
                        if(LED1_FLASH_count <= LED1_S1)
                        {
                                LED1_ON();
                        }
                        if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S10) )
                        {
                                LED1_OFF();
                        }
                        if ( LED1_FLASH_count > LED1_S10 )
                        {
                                LED1_FLASH_count =0;
                                LED1_ON();
                        }
                        break;

                case LED_FLASH_slow:
                        if(LED1_FLASH_count <= LED1_S1)
                        {
                                LED1_ON();
                        }
                        if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S20) )
                        {
                                LED1_OFF();
                        }
                        if ( LED1_FLASH_count > LED1_S20 )
                        {
                                LED1_FLASH_count =0;
                                LED1_ON();
                        }
                        break;

                case LED_FLASH_on:
                        LED1_FLASH_count =0;
                        LED1_ON();
                        break;

                case LED_FLASH_off:
                        LED1_FLASH_count =0;
                        LED1_OFF();
                        break;

                case LED_FLASH_oneTime:
                        if(LED1_FLASH_count <= LED1_S1)
                        {
                                LED1_ON();
                        }
                        if(LED1_FLASH_count > LED1_S1)
                        {
                                LED1_status = LED_FLASH_off;
                                LED1_FLASH_count =0;
                                LED1_OFF();
                        }
                        break;
        }

        if( LED1_FLASH_count > LED1_S_END)
        {
                LED1_FLASH_count =0;
        }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

80

主题

1035

帖子

0

粉丝