你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32G0学习手册——使用SWD接口进行调试 (HAL库)

[复制链接]
STMCU小助手 发布时间:2021-11-11 20:00
1,修改代码的地方
上一章讲到了应用CubeMX产生了项目源文件,现在用CubeIDE打开,我们会看到很多:
/* USER CODE BEGIN 1*/
/* USER CODE END 1*/
就是说,你的代码要放在这些标记的中间,如果我们返回去CubeMX修改了配置,重新生成了代码,但是放在这些标记中间的代码是不会被修改的。
另外,对于自动产生的代码,尽量不要修改。

20200213090511608.jpg


2,MCU本身的初始化
这里主要包括时钟、IO口、Timer、串口等的初始化
其中MX_IWDG_Init() 是独立看门狗的初始化,这个先把它注掉,不然不好调试
  1. int main(void)
  2. {
  3.   /* USER CODE BEGIN 1 */

  4.   /* USER CODE END 1 */


  5.   /* MCU Configuration--------------------------------------------------------*/

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

  8.   /* USER CODE BEGIN Init */

  9.   /* USER CODE END Init */

  10.   /* Configure the system clock */
  11.   SystemClock_Config();

  12.   /* USER CODE BEGIN SysInit */

  13.   /* USER CODE END SysInit */

  14.   /* Initialize all configured peripherals */
  15.   MX_GPIO_Init();
  16.   MX_DMA_Init();
  17.   MX_TIM3_Init();
  18.   MX_USART1_UART_Init();
  19.   MX_USART2_UART_Init();
  20.   //MX_IWDG_Init();
  21.   MX_RTC_Init();
复制代码

3,MCU初始化,读写内部FLASH,写自定义配置
STM32G031C8单片机内部都有很大的内部FLASH空间,我们可以拿出一点来作为自定义的配置空间,这样就不需要额外的EEPROM,但是内部FLASH的稳定性及读写速度、读写便利性不如EEPROM,一般运行过程中,不频繁读写FLASH还是没问题的。
这是写自定义配置的入口:

  1.   /* USER CODE BEGIN 2 */

  2.   //---1, MCU CONFIGURE ------------
  3.   thisMCU_init();
复制代码
进去看一下:
这里是读FLASH的程序:这里是从baseFlashAdd31地址开始,读40个字节
baseFlashAdd31=0x0800F800,即最后一个2K的程序空间作为自定义空间,因为FLASH是整块擦除的,所以最好定义整块空间。
  1. //-----------------------------
  2. void  dtkReadConfigure(void)
  3. {
  4.         dtkReadFlash(baseFlashAdd31, 40);
  5. }
复制代码
  1. //-----------------------------
  2. void  dtkReadFlash(uint32_t  startAdd,  uint16_t countToRead)
  3. {
  4.         __IO uint32_t   data32 = 0;
  5.         uint8_t         i=0;
  6.         uint32_t        tempAdd=0;

  7.         tempAdd = startAdd;
  8.         for(i=0; i<countToRead; i=i+4)
  9.         {

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

  12.                 dtkReadedConfig<i> = (data32>>24) & 0x000000FF;
  13.               </i>  dtkReadedConfig[i+1] = (data32>>16) & 0x000000FF;
  14.                 dtkReadedConfig[i+2] = (data32>>8) & 0x000000FF;
  15.                 dtkReadedConfig[i+3] = data32 & 0x000000FF;

  16.                 tempAdd = tempAdd +4;
  17.         }
  18. }
复制代码
  1. //-----扇区 32 -------------------------
  2. #define    baseFlashAdd31    0x0800F800
复制代码

20200213140513841.jpg


下面是写FLASH的程序:

  1. void  dtkWriteConfigure(void)
  2. {
  3.         dtkWriteFlash(baseFlashAdd31, dtkWritedConfig, 40);
  4. }
复制代码
  1. /* -----------------------------------------------------------------
  2. *  startAdd: 必须为某一页的起始地址:baseFlashAdd60 -baseFlashAdd63
  3. *  countToWrite必须为8的倍数(即一次写入为Two Word的倍数)
  4. *
  5. *  ----------------------------------------------------------------*/
  6. void  dtkWriteFlash(uint32_t  startAdd,  uint8_t  *writeData,  uint16_t countToWrite)
  7. {
  8.         uint32_t    i=0;
  9.         uint64_t    tempWriteData;
  10.         uint32_t    tempWriteAdd;
  11.         HAL_StatusTypeDef  status;

  12.         uint32_t     tempW1=0;
  13.         uint32_t     tempW2=0;

  14.     HAL_FLASH_Unlock();
  15.     //HAL_FLASH_Unlock();

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


  20.     uint32_t PageError = 0;

  21.     HAL_FLASHEx_Erase(&f, &PageError);

  22.         for(i=0; i<countToWrite ; i=i+8)
  23.     {
  24.           tempW1=0;
  25.           tempW2=0;
  26.           tempWriteData=0;

  27. <span style="font-style: italic;"><span style="font-style: normal;">          tempW1 = writeData;
  28.           tempW1 = tempW1<<8;
  29.           tempW1 = tempW1 | writeData[i+1];

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

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


  34.           tempW2 = writeData[i+4];
  35.           tempW2 = tempW2<<8;
  36.           tempW2 = tempW2 | writeData[i+5];

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

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

  41.           tempWriteData = tempWriteData|tempW2;
  42.           tempWriteData = tempWriteData<<32;
  43.           tempWriteData = tempWriteData | tempW1;

  44.           tempWriteAdd = startAdd + i;

  45.           //HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, tempWriteAdd, tempWriteData);
  46.           HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, tempWriteAdd, tempWriteData);

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

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

  51.       // In case of error, stop programation procedure
  52.       if (status != HAL_OK)
  53.       {
  54.         break;
  55.       }

  56.     }
  57. }</span></span>
复制代码

在本项目中,我们开辟了40个字节的自定义配置,其中第一个字节表示配置是否写过了,如果是0xA5,表示配置已经写过了,第二个字节是ModBus地址,默认写入0xF0,最后一个字节是前面39个字节的和保留低8位(和校验),如果校验不通过,则重写FLASH。
其它的字节没有用到。

  1. //--------------
  2. void  thisMCU_init(void)
  3. {
  4.         uint8_t   tempXY=0;

  5.         dtkReadConfigure();

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

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

  13.                         dtkWriteConfigure();
  14.                         break;

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

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

  20.                         dtkWriteConfigure();
  21.                         break;

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

  29.         readDataReportModel();
  30. }
复制代码

4,MCU初始化,读取本项目运行模式
主要是读取IO口S1,S2的状态,组合成有4种运行模式:就是分别将DRF1609H设置为Router或End Device,主动上报数据或等待ModBus指令上报数据,其中如果将DRF1609H设置成End Device,同时是自动上报数据,则自动进入低功耗上报数据状态。
  1. #define   EndDeviceLowPower         1
  2. #define   EndDeviceWaitModbus       2
  3. #define   RouterActiveReport        3
  4. #define   RouterWaitModbus          4
复制代码
  1. //--------------
  2. void  readDataReportModel(void)
  3. {
  4.         uint8_t   val1=0, val2=0;

  5.         val1 = HAL_GPIO_ReadPin(GPIOB, S1_Pin);
  6.         val2 = HAL_GPIO_ReadPin(GPIOB, S2_Pin);

  7.         //---------
  8.         if( (val1==0) & (val2==0) )
  9.         {
  10.                 sysRuningModel = EndDeviceLowPower;
  11.         }

  12.         //---------
  13.         if( (val1==0) & (val2==1) )
  14.         {
  15.                 sysRuningModel = EndDeviceWaitModbus;
  16.         }


  17.         //---------
  18.         if( (val1==1) & (val2==0) )
  19.         {
  20.                 sysRuningModel = RouterActiveReport;
  21.         }

  22.         //---------
  23.         if( (val1==1) & (val2==1) )
  24.         {
  25.                 sysRuningModel = RouterWaitModbus;
  26.         }


  27.         //---------------  ----------------
  28.         if(val2 ==1)
  29.         {
  30.                 dataReportModel = waitModBus;
  31.         }
  32.         else
  33.         {
  34.                 dataReportModel = activeReport;
  35.         }

  36. }
复制代码

5,LED灯的初始化
本项目中用了2个LED,LED1周期性的闪,用来指示软件是否正常运行,LED2用来指示DRF160H是否加入网络及数据的收发。
LED的闪,我们用到了Timer3的中断,在Timer3的中断里计时,控制LED的闪、灭时间,首先在time.c文件里加上Timer3的中断函数:

  1. /* USER CODE BEGIN 1 */
  2. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  3. {
  4.     if (htim->Instance == htim3.Instance)   //---Timer3 中断入口 ---------
  5.     {
  6.             LED1_FLASH();
  7.             LED2_FLASH();

  8.             newEventCount();

  9.             HAL_UART_ReceivedCount();

  10.             //HAL_I2C_ReceivedCount();
  11.     }
  12. }

  13. /* USER CODE END 1 */
复制代码


即每次timer3中断后,都会执行下LED1_FLASH(),再进去里面看看:原来是控制LED1闪的速度。

  1. //---------------------------
  2. void LED1_FLASH(void)
  3. {
  4.         LED1_FLASH_count++;

  5.         switch (LED1_status)
  6.         {
  7.                 case LED_FLASH_quick:
  8.                         if(LED1_FLASH_count <= LED1_S1)
  9.                         {
  10.                                 LED1_ON();
  11.                         }
  12.                         if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S2) )
  13.                         {
  14.                                 LED1_OFF();
  15.                         }
  16.                         if ( LED1_FLASH_count > LED1_S2 )
  17.                         {
  18.                                 LED1_FLASH_count =0;
  19.                                 LED1_ON();
  20.                         }
  21.                         break;

  22.                 case LED_FLASH_medium:
  23.                         if(LED1_FLASH_count <= LED1_S1)
  24.                         {
  25.                                 LED1_ON();
  26.                         }
  27.                         if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S10) )
  28.                         {
  29.                                 LED1_OFF();
  30.                         }
  31.                         if ( LED1_FLASH_count > LED1_S10 )
  32.                         {
  33.                                 LED1_FLASH_count =0;
  34.                                 LED1_ON();
  35.                         }
  36.                         break;

  37.                 case LED_FLASH_slow:
  38.                         if(LED1_FLASH_count <= LED1_S1)
  39.                         {
  40.                                 LED1_ON();
  41.                         }
  42.                         if( (LED1_FLASH_count > LED1_S1) && (LED1_FLASH_count <= LED1_S20) )
  43.                         {
  44.                                 LED1_OFF();
  45.                         }
  46.                         if ( LED1_FLASH_count > LED1_S20 )
  47.                         {
  48.                                 LED1_FLASH_count =0;
  49.                                 LED1_ON();
  50.                         }
  51.                         break;

  52.                 case LED_FLASH_on:
  53.                         LED1_FLASH_count =0;
  54.                         LED1_ON();
  55.                         break;

  56.                 case LED_FLASH_off:
  57.                         LED1_FLASH_count =0;
  58.                         LED1_OFF();
  59.                         break;

  60.                 case LED_FLASH_oneTime:
  61.                         if(LED1_FLASH_count <= LED1_S1)
  62.                         {
  63.                                 LED1_ON();
  64.                         }
  65.                         if(LED1_FLASH_count > LED1_S1)
  66.                         {
  67.                                 LED1_status = LED_FLASH_off;
  68.                                 LED1_FLASH_count =0;
  69.                                 LED1_OFF();
  70.                         }
  71.                         break;
  72.         }

  73.         if( LED1_FLASH_count > LED1_S_END)
  74.         {
  75.                 LED1_FLASH_count =0;
  76.         }
  77. }
复制代码


收藏 评论0 发布时间:2021-11-11 20:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版