[求助] RTX下浮点数类型数值无法正常输出问题

Tobey   2016-8-20 20:43 楼主
在裸奔程序中,循环获取7个通道的AD值并将转换为电阻后逐个打印,串口助手中显示正常,代码如下;
  1. i=0;
  2. while (1)
  3. {
  4. Change_Channel(i);
  5. ADS1248_Start(ADC_MODE_SINGLECOV);
  6. ADS1248_WaitBusy();
  7. Data=ADS1248_Read();
  8. R = (Data/8388607.0/8)*2*820+180;
  9. printf("%5.2f, ",R);
  10. i++;
  11. if(i==7)
  12. {
  13. i=0;
  14. printf("\n");
  15. };
  16. }
现将其移植到RTX系统中,启用单任务时运行正常:
  1. __task void adcTask (void) {
  2. ADS1248_Init(ADC_GAIN_8|ADC_SPS_20);
  3. int8_t chanel = 0;
  4. float R;
  5. for (;;) {
  6. int32_t Data;
  7. Data = ADS1248_Channel_Data(chanel);
  8. R = (Data/8388607.0/8)*2*820+180;
  9. printf("%5.2f, ", R);
  10. chanel++;
  11. if(chanel==7)
  12. {
  13. printf("\n");
  14. chanel=0;
  15. };
  16. os_dly_wait(10);
  17. }
  18. }
单任务.png 接着将AD转换与打印数据分离实现,启用一个新的任务用于打印AD数据,因此在AD任务中将7个通道的AD值逐个存入float类型数组R中,并在打印任务中打印AD值。结果AD值无法正常显示,数据显示如下图所示,, 请问有人遇到过类似的情况吗?是什么原因造成的? (补充:测试时发现将SPI的时钟配置修改为70KHz后,AD值将正常显示,,原始SPI时钟频率为140KHz,根据AD数据手册时序要求得到SPI时钟频率的上限为2MHz,所以应该不是SPI的问题,应该只是有所牵连,具体问题出自于哪还望大神们解惑!!)
  1. __task void printfTask (void) {
  2. for (;;) {
  3. int i;
  4. for(i=0; i<7; i++)
  5. {
  6. printf("%5.2f, ", (chanelDataArray[i]/8388607.0/8)*2*820+180);
  7. }
  8. printf("\n");
  9. os_dly_wait(100);
  10. }
  11. }
2.png 本帖最后由 Tobey 于 2016-8-20 20:58 编辑

回复评论 (16)

采用直接在ADC任务中将AD值转换为电阻值,然后存储至数组中,接着在打印任务里取出的方式,串口调试助手中显示的AD值显示正常~~也就是说不能在打印任务中进行转换,,,why???
点赞  2016-8-21 10:05
前天刚遇到操作系统中的浮点数运算出错的问题,我是在tqOS上运行出错的,后来改了源码就行了,但是我的错误结果和你的不太一样,我觉得跟我的问题不一样,估计是因为程序设计上的问题,不是操作系统的问题,你可以把完整的程序拿出来看看。
亚里士缺德
点赞  2016-8-30 09:26
引用: 汤权 发表于 2016-8-30 09:26 前天刚遇到操作系统中的浮点数运算出错的问题,我是在tqOS上运行出错的,后来改了源码就行了,但是我的错误 ...
好的,麻烦帮我看看--(我是采用HAL库进行开发的) RTX配置: QQ图片20160901092931.png 这是main.c文件
  1. /**
  2. ******************************************************************************
  3. * File Name : main.c
  4. * Description : Main program body
  5. ******************************************************************************
  6. *
  7. * COPYRIGHT(c) 2016 STMicroelectronics
  8. *
  9. ******************************************************************************
  10. */
  11. /* Includes ------------------------------------------------------------------*/
  12. #include "stm32f1xx_hal.h"
  13. #include "spi.h"
  14. #include "tim.h"
  15. #include "usart.h"
  16. #include "gpio.h"
  17. /* USER CODE BEGIN Includes */
  18. #include <RTL.h>
  19. #include "ADS1248.h"
  20. /* USER CODE END Includes */
  21. /* Private variables ---------------------------------------------------------*/
  22. /* USER CODE BEGIN PV */
  23. /* Private variables ---------------------------------------------------------*/
  24. OS_TID t_adc; /* assigned task id of task: adcTask */
  25. OS_TID t_printf; /* assigned task id of task: printfTask */
  26. OS_TID t_test; /* assigned task id of task: testTask */
  27. volatile int32_t chanelDataArray[7]; /* AD数据 */
  28. /* USER CODE END PV */
  29. /* Private function prototypes -----------------------------------------------*/
  30. void SystemClock_Config(void);
  31. void Error_Handler(void);
  32. /* USER CODE BEGIN PFP */
  33. /* Private function prototypes -----------------------------------------------*/
  34. /* USER CODE END PFP */
  35. /* USER CODE BEGIN 0 */
  36. /**
  37. * @brief 测试任务.
  38. * @param None.
  39. * @note 设置LED1每秒闪烁一次.
  40. * @retval None
  41. */
  42. __task void testTask (void) {
  43. for (;;) {
  44. HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
  45. os_dly_wait(1000);
  46. }
  47. }
  48. /**
  49. * @brief 打印任务,用于打印串口数据.
  50. * @param None.
  51. * @note 当前打印数据仅AD通道数组中的AD数据
  52. * @retval None
  53. */
  54. __task void printfTask (void) {
  55. for (;;) {
  56. int i;
  57. float R;
  58. for(i=0; i<7; i++)
  59. {
  60. // // R = Ad/Full/Gain*2*Rref+R2
  61. /*当配置APB1的频率为36MHz时,使用下列两行将会造成输出结果不正确*/
  62. R = chanelDataArray[i]/8388607.0/8*2*810+180;
  63. printf("%5.2d , %4.2f ;", chanelDataArray[i], R);
  64. /*采用下列方法都显示正常*/
  65. // printf("%5.2d , %4.2f ;", chanelDataArray[i], chanelDataArray[i]/8388607.0/8.0*2.0*810.0 + 180);
  66. }
  67. printf("\n");
  68. os_dly_wait(100);
  69. }
  70. }
  71. /**
  72. * @brief ADC任务.
  73. * @param None.
  74. * @note 循环获取7个AD通道的AD值
  75. * @retval None
  76. */
  77. __task void adcTask (void) {
  78. os_dly_wait(20);
  79. ADS1248_Init(ADC_GAIN_8|ADC_SPS_20); //初始化 AD1248
  80. int8_t chanel = 0;
  81. for (;;) {
  82. int32_t Data;
  83. Data = ADS1248_Channel_Data(chanel);
  84. chanelDataArray[chanel] = Data;
  85. chanel++;
  86. if(chanel==7)
  87. {
  88. chanel=0;
  89. };
  90. os_dly_wait(10);
  91. }
  92. }
  93. /**
  94. * @brief 初始化任务.
  95. * @param None.
  96. * @note 用于创建任务,当任务都创建完成时,其使命达成自行销毁.
  97. * @retval None
  98. */
  99. __task void initTask (void) {
  100. t_adc = os_tsk_create(adcTask,1);
  101. t_printf = os_tsk_create(printfTask,1);
  102. t_test = os_tsk_create(testTask,1);
  103. os_tsk_delete_self();
  104. }
  105. /* USER CODE END 0 */
  106. int main(void)
  107. {
  108. /* USER CODE BEGIN 1 */
  109. /* USER CODE END 1 */
  110. /* MCU Configuration----------------------------------------------------------*/
  111. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  112. HAL_Init();
  113. /* Configure the system clock */
  114. SystemClock_Config();
  115. /* Initialize all configured peripherals */
  116. MX_GPIO_Init();
  117. MX_SPI2_Init();
  118. MX_TIM1_Init();
  119. MX_TIM2_Init();
  120. MX_TIM3_Init();
  121. MX_TIM4_Init();
  122. MX_USART1_UART_Init();
  123. /* USER CODE BEGIN 2 */
  124. HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_2);
  125. HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_1);
  126. HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_2);
  127. HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_1);
  128. HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_2);
  129. HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_3);
  130. // 初始化RTX内核并启动初始化任务,此后应用程序将在任务中继续执行
  131. // os_sys_init(initTask);
  132. os_sys_init_prio(initTask,3);
  133. /* USER CODE END 2 */
  134. /* Infinite loop */
  135. /* USER CODE BEGIN WHILE */
  136. while (1)
  137. {
  138. /* USER CODE END WHILE */
  139. /* USER CODE BEGIN 3 */
  140. }
  141. /* USER CODE END 3 */
  142. }
  143. /** System Clock Configuration
  144. */
  145. void SystemClock_Config(void)
  146. {
  147. RCC_OscInitTypeDef RCC_OscInitStruct;
  148. RCC_ClkInitTypeDef RCC_ClkInitStruct;
  149. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  150. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  151. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  152. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  153. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  154. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  155. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  156. {
  157. Error_Handler();
  158. }
  159. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  160. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  161. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  162. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  163. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  164. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  165. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  166. {
  167. Error_Handler();
  168. }
  169. HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  170. HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  171. /* SysTick_IRQn interrupt configuration */
  172. HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  173. }
  174. /* USER CODE BEGIN 4 */
  175. int fputc(int ch,FILE *f)
  176. {
  177. uint8_t temp[1]={ch};
  178. HAL_UART_Transmit(&huart1,temp,1,2);
  179. return ch;
  180. }
  181. /* USER CODE END 4 */
  182. /**
  183. * @brief This function is executed in case of error occurrence.
  184. * @param None
  185. * @retval None
  186. */
  187. void Error_Handler(void)
  188. {
  189. /* USER CODE BEGIN Error_Handler */
  190. /* User can add his own implementation to report the HAL error return state */
  191. while(1)
  192. {
  193. }
  194. /* USER CODE END Error_Handler */
  195. }
  196. #ifdef USE_FULL_ASSERT
  197. /**
  198. * @brief Reports the name of the source file and the source line number
  199. * where the assert_param error has occurred.
  200. * @param file: pointer to the source file name
  201. * @param line: assert_param error line source number
  202. * @retval None
  203. */
  204. void assert_failed(uint8_t* file, uint32_t line)
  205. {
  206. /* USER CODE BEGIN 6 */
  207. /* User can add his own implementation to report the file name and line number,
  208. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  209. /* USER CODE END 6 */
  210. }
  211. #endif
  212. /**
  213. * @}
  214. */
  215. /**
  216. * @}
  217. */
  218. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
以下是时钟配置:(SPI2采用256分频系数,APB2频率为36MHz时为140KHz,APB2为18MHz时为70KHz) QQ截图20160831201007.png 本帖最后由 Tobey 于 2016-9-1 15:07 编辑
点赞  2016-9-1 09:31
首先假设你的ADS1248芯片的硬件驱动程序都是对的(我就没详细看了),直接看你的主程序,有几个想说的,但不一定是问题所在。
1、printftask中你说“当配置APB2的频率为36MHz时,使用下列两行将会造成输出结果不正确”, 看程序的话你应该用的是SPI2作为通信总线,这样的话APB2是不影响SPI2的速率的,可能是APB2影响了串口1的时钟导致波特率出问题,但是如果你的程序的串口初始化函数里面自适应了APB2的时钟的话那就不是这个问题,而且你后面也说了下一句程序是没问题的。

2、ADS1248_ReToTemp函数没看见定义在哪。

3、你说把APB2的频率改了之后出现问题,我感觉应该是系统问题,我看你在main函数里面初始化了定时器1234,234作为PWM发生器,定时器1做什么了,系统定时器应该是systick不是tim1啊,不明觉厉

4、你的系统开启了时间片轮转,先把时间片轮转的关了,然后把任务的优先级设置为:test任务优先级最低,adc采样任务优先级其次,打印任务优先级最高试试吧。

毕竟不是我在调试,问题的现象我不清楚,不好确定原因所在。
亚里士缺德
点赞  2016-9-1 10:44
引用: 汤权 发表于 2016-9-1 10:44
首先假设你的ADS1248芯片的硬件驱动程序都是对的(我就没详细看了),直接看你的主程序,有几个想说的,但 ...

打错了,应该是APB1的频率,测试时没使用ADS1248_ReToTemp函数,所以没贴上,测试时R赋值的就是ADS1248_ReToTemp的参数部分,,tim1我使用来控制电机的,,,
点赞  2016-9-1 11:34
引用: 汤权 发表于 2016-9-1 10:44
首先假设你的ADS1248芯片的硬件驱动程序都是对的(我就没详细看了),直接看你的主程序,有几个想说的,但 ...

把APB1的频率升高后,ADS1248的初始化部分也会出问题,需要减少一个寄存器的写入操作,,不过初始化时往MUX1中写入0x00倒是也没问题,但是,APB1的频率降低后这些问题就都不见了,,,
点赞  2016-9-1 11:37
引用: 汤权 发表于 2016-9-1 10:44
首先假设你的ADS1248芯片的硬件驱动程序都是对的(我就没详细看了),直接看你的主程序,有几个想说的,但 ...

输出错误主要就是不稳定,一阵一阵的波动,,
33.png
点赞  2016-9-1 11:41
引用: 汤权 发表于 2016-9-1 10:44
首先假设你的ADS1248芯片的硬件驱动程序都是对的(我就没详细看了),直接看你的主程序,有几个想说的,但 ...

改为抢占式也是一样的结果,根据你说的TIM1的问题,刚刚测试了发现,如果将与TIM1相关的电机任务关闭的话,串口助手中显示的数据是正常的,

只要启动电机任务,串口助手中的数据就炸了~~显示的基本都是通道断开时的数据,偶尔显示正确转换值、、、
这是为什么呢?

前面发的是出现问题时备份的项目程序代码,当前项目的main.c文件是这样的:(最近在测试PID控制,adc任务略乱~~)
  1. /**
  2.   ******************************************************************************
  3.   * File Name          : main.c
  4.   * Description        : Main program body
  5.   ******************************************************************************
  6.   *
  7.   * COPYRIGHT(c) 2016 STMicroelectronics
  8.   *
  9.   ******************************************************************************
  10.   */
  11. /* Includes ------------------------------------------------------------------*/
  12. #include "stm32f1xx_hal.h"
  13. #include "spi.h"
  14. #include "tim.h"
  15. #include "usart.h"
  16. #include "gpio.h"

  17. /* USER CODE BEGIN Includes */
  18. #include <RTL.h>
  19. #include "ADS1248.h"
  20. #include "step_motor_driver.h"
  21. #include "pid_driver.h"
  22. /* USER CODE END Includes */

  23. /* Private variables ---------------------------------------------------------*/

  24. /* USER CODE BEGIN PV */
  25. /* Private variables ---------------------------------------------------------*/
  26. OS_TID t_adc;                        /* assigned task id of task: adcTask */
  27. OS_TID t_printf;                        /* assigned task id of task: printfTask */
  28. OS_TID t_motor;                        /* assigned task id of task: motorTask */
  29. OS_TID t_test;                        /* assigned task id of task: testTask */
  30. volatile uint32_t chanelDataArray[7];                                                                                                /* AD数据 */
  31. volatile float chanelTempArray[7];                                 /* 各通道温度数组 */
  32. const float chanelDrift[7] = { 0.6, 0.25, -0.3, -0.35, 0, 0, -0.3 };
  33. static PID PID_Chanel[7];

  34. /* USER CODE END PV */

  35. /* Private function prototypes -----------------------------------------------*/
  36. void SystemClock_Config(void);
  37. void Error_Handler(void);

  38. /* USER CODE BEGIN PFP */
  39. /* Private function prototypes -----------------------------------------------*/

  40. /* USER CODE END PFP */

  41. /* USER CODE BEGIN 0 */

  42. /**
  43.   * @brief  步进电机控制测试任务.
  44.   * @param  None.
  45.   * @note   两个静态变量分别用于控制电机步进控制与电机配置控制.
  46.         *      @arg openTIM: 0表示中断未开启,1表示中断已开启
  47.         *      @arg microStep: 0、1、2、3分别代表细分级数:FULL、HALF、QUARTER、EIGHTH
  48.         *           每次切换细分级数时同时修改电机转动方向。
  49.         *                                                 FULL   -> 200节拍(一圈)  (顺时针旋转)
  50.         *                                                 HALF   -> 400节拍(一圈)  (逆时针旋转)
  51.         *                                                 FOUTH  -> 800节拍(一圈)  (顺时针旋转)
  52.         *                                                 EIGTH  -> 1600节拍(一圈) (逆时针旋转)
  53.   * @retval None
  54.   */
  55. __task void motorTask (void) {
  56.         BSP_STEP_MOTOR_Init();                        // 初始化电机
  57.         uint8_t openTIM = 1; // 默认初始化时Step为0,此时计时器中断应该为关闭状态,这里为了进行测试设置为1
  58.         uint8_t microStep = 0;        // 细分步数标志
  59.   for (;;) {
  60.                 if(openTIM == 0 && STEP_MOTOR_Msg.Step > 0)        // 当Step>0且计时器处于关闭状态时开启计时器
  61.                 {
  62.                         HAL_TIM_Base_Start_IT(&htim1);
  63.                         openTIM=1;
  64.                 }
  65.                 if(openTIM == 1 && STEP_MOTOR_Msg.Step == 0)        // 当计时器处于开启状态且Step已为0时设置计时器标志位为1
  66.                 {
  67.                         openTIM = 0;
  68.                         os_dly_wait(100);
  69.                         switch(microStep)
  70.                         {
  71.                                 case 0: // FULL FORWARD
  72.                                         STEP_MOTOR_Msg.Dir = FORWARD;
  73.                                         STEP_MOTOR_Msg.MicroStep = FULL;
  74.                                         STEP_MOTOR_Msg.Step = 200;
  75.                                         microStep++;
  76.                                         break;
  77.                                 case 1:        // HALF REVERSAL
  78.                                         STEP_MOTOR_Msg.Dir = REVERSAL;
  79.                                         STEP_MOTOR_Msg.MicroStep = HALF;
  80.                                         STEP_MOTOR_Msg.Step = 400;
  81.                                         microStep++;
  82.                                         break;
  83.                                 case 2: // QUARTER FORWARD
  84.                                         STEP_MOTOR_Msg.Dir = FORWARD;
  85.                                         STEP_MOTOR_Msg.MicroStep = QUARTER;
  86.                                         STEP_MOTOR_Msg.Step = 800;
  87.                                         microStep++;
  88.                                         break;
  89.                                 case 3: // EIGHTH REVERSAL
  90.                                         STEP_MOTOR_Msg.Dir = REVERSAL;
  91.                                         STEP_MOTOR_Msg.MicroStep = EIGHTH;
  92.                                         STEP_MOTOR_Msg.Step = 1600;
  93.                                         microStep = 0;
  94.                                         break;
  95.                                 default:
  96.                                         break;
  97.                         }
  98.                 }
  99.                 os_tsk_pass();//上述判断条件语句执行完成后交出CPU控制权
  100.   }
  101. }

  102. /**
  103.   * @brief  测试任务.
  104.   * @param  None.
  105.   * @note   设置LED1每秒闪烁一次.
  106.   * @retval None
  107.   */
  108. __task void testTask (void) {
  109.   for (;;) {
  110.                 HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
  111.                 os_dly_wait(1000);
  112.   }
  113. }

  114. /**
  115.   * @brief  打印任务,用于打印串口数据.
  116.   * @param  None.
  117.   * @note   当前仅打印AD值及与其对应的温度值
  118.   * @retval None
  119.   */
  120. __task void printfTask (void) {
  121.        
  122.   for (;;) {
  123.                
  124.                 int i;
  125.                 float Temp;
  126.                 for(i=0; i<7; i++)
  127.                 {
  128.                         // R = Ad/Full/Gain*2*Rref+R2
  129. //                        R = chanelDataArray[i]/0x7fffff/8*2*810+180;  
  130.                         Temp = ADS1248_AdToTemp(chanelDataArray[i]);//直接根据AD值查表得到温度值
  131.                         printf("%5.2d ,  %4.2f  ;", chanelDataArray[i], Temp);
  132.                        
  133.                 }
  134.                 printf("\n");
  135.                 os_dly_wait(100);
  136.   }
  137. }

  138. /**
  139.   * @brief  ADC及PID测试任务.
  140.   * @param  None.
  141.   * @note   循环获取7个AD通道的AD值,并将AD值存储至数组中
  142.         *                                 根据转换得到的温度值进性PID控制
  143.         *                                 chanel:通道编号
  144.         *                                 PIDSet[7]:标识各通道PID控制时间间隔
  145.         *                                        chanelDataArray[7]:存储各通道AD值
  146.         *                                        chanelTempArray[7]:存储各通道AD值对应的温度值
  147.   * @retval None
  148.   */
  149. __task void adcTask (void) {
  150.         int i;
  151.         for(i=0; i<7; i++)//PID初始化
  152.         {
  153.                 PID_Init(&PID_Chanel[i]);
  154.                 //PID配置,设置各通道Kp,Ki,Kd值,SetPoint值应该在设置温度时进性配置,此处用于测试对其进行配置
  155.                 PID_SetPoint(&PID_Chanel[i], 40); //设置 PID 调节的目标值
  156.                 PID_SetKp(&PID_Chanel[i], 2); //设置 PID 的 Kp 值
  157.                 PID_SetKi(&PID_Chanel[i], 0); //设置 PID 的 Ki 值
  158.                 PID_SetKd(&PID_Chanel[i], 0); //设置 PID 的 Kd 值
  159.         }
  160.        
  161.         os_dly_wait(17);
  162.         ADS1248_Init(ADC_GAIN_16|ADC_SPS_20);             //初始化 AD1248
  163.         int8_t chanel = 0;
  164.         int16_t PIDSet[7] = { 0, 0, 0, 0, 0, 0, 0 };
  165.   for (;;) {
  166.         int32_t Data;

  167.         Data = ADS1248_Channel_Data(chanel);
  168.         chanelTempArray[chanel] = ADS1248_AdToTemp(Data);
  169.        
  170.         if(PIDSet[chanel] == 30) // 间隔指定时间进入一次PID控制
  171.         {
  172.                 /*如果当前温度与设定值相差50度,则进入PID控制范围*/
  173.                 if( (PID_Chanel[chanel].SetPoint - chanelTempArray[chanel] < 50 && PID_Chanel[chanel].SetPoint - chanelTempArray[chanel] > 0)
  174.                                 || (PID_Chanel[chanel].SetPoint - chanelTempArray[chanel] > -50 && PID_Chanel[chanel].SetPoint - chanelTempArray[chanel] < 0))
  175.                 {
  176.                         uint8_t pulse = PID_IncCalc(&PID_Chanel[chanel],chanelTempArray[chanel]);//采用PID增量模式
  177.                         printf("puse%d: %d,  temp: %f\n",chanel, pulse, chanelTempArray[chanel]);
  178.                         PID_IncPWMCtr(chanel, pulse);//增量式PID的PWM控制
  179.                 }
  180.                 PIDSet[chanel] = 0;
  181.                
  182.         }
  183.        
  184.         chanelDataArray[chanel] = Data;
  185.         PIDSet[chanel]++;
  186.         chanel++;
  187.         if(chanel==7)
  188.         {
  189.                 chanel=0;
  190.         };       
  191.         os_dly_wait(10);
  192.        
  193.   }
  194. }

  195. /**
  196.   * @brief  初始化任务.
  197.   * @param  None.
  198.   * @note   用于创建任务,当任务都创建完成时,其使命达成自行销毁.
  199.   * @retval None
  200.   */
  201. __task void initTask (void) {
  202.         t_adc = os_tsk_create(adcTask,1);
  203.         t_printf = os_tsk_create(printfTask,1);
  204.         t_motor = os_tsk_create(motorTask,1);
  205.         t_test = os_tsk_create(testTask,1);
  206.         os_tsk_delete_self();
  207. }
  208. /* USER CODE END 0 */

  209. int main(void)
  210. {

  211.   /* USER CODE BEGIN 1 */

  212.   /* USER CODE END 1 */

  213.   /* MCU Configuration----------------------------------------------------------*/

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

  216.   /* Configure the system clock */
  217.   SystemClock_Config();

  218.   /* Initialize all configured peripherals */
  219.   MX_GPIO_Init();
  220.   MX_SPI2_Init();
  221.   MX_TIM1_Init();
  222.   MX_TIM2_Init();
  223.   MX_TIM3_Init();
  224.   MX_TIM4_Init();
  225.   MX_USART1_UART_Init();

  226.   /* USER CODE BEGIN 2 */

  227.         HAL_TIM_PWM_Start_IT(&htim2,TIM_CHANNEL_2);

  228.         HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_1);               
  229.         HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_2);               
  230.        
  231.         HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_1);       
  232.         HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_2);       
  233.         HAL_TIM_PWM_Start_IT(&htim4,TIM_CHANNEL_3);       

  234.         // 初始化RTX内核并启动初始化任务,此后应用程序将在任务中继续执行
  235. //        os_sys_init(initTask);
  236.         os_sys_init_prio(initTask,3);
  237.   /* USER CODE END 2 */

  238.   /* Infinite loop */
  239.   /* USER CODE BEGIN WHILE */
  240.   while (1)
  241.   {
  242.   /* USER CODE END WHILE */

  243.   /* USER CODE BEGIN 3 */

  244.   }
  245.   /* USER CODE END 3 */

  246. }

  247. /** System Clock Configuration
  248. */
  249. void SystemClock_Config(void)
  250. {

  251.   RCC_OscInitTypeDef RCC_OscInitStruct;
  252.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

  253.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  254.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  255.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  256.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  257.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  258.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  259.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  260.   {
  261.     Error_Handler();
  262.   }

  263.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  264.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  265.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  266.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  267.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  268.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  269.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  270.   {
  271.     Error_Handler();
  272.   }

  273.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  274.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  275.   /* SysTick_IRQn interrupt configuration */
  276.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  277. }

  278. /* USER CODE BEGIN 4 */
  279. int fputc(int ch,FILE *f)
  280. {
  281.     uint8_t temp[1]={ch};
  282.     HAL_UART_Transmit(&huart1,temp,1,2);
  283.                 return ch;
  284. }
  285. /* USER CODE END 4 */

  286. /**
  287.   * @brief  This function is executed in case of error occurrence.
  288.   * @param  None
  289.   * @retval None
  290.   */
  291. void Error_Handler(void)
  292. {
  293.   /* USER CODE BEGIN Error_Handler */
  294.   /* User can add his own implementation to report the HAL error return state */
  295.   while(1)
  296.   {
  297.   }
  298.   /* USER CODE END Error_Handler */
  299. }

  300. #ifdef USE_FULL_ASSERT

  301. /**
  302.    * @brief Reports the name of the source file and the source line number
  303.    * where the assert_param error has occurred.
  304.    * @param file: pointer to the source file name
  305.    * @param line: assert_param error line source number
  306.    * @retval None
  307.    */
  308. void assert_failed(uint8_t* file, uint32_t line)
  309. {
  310.   /* USER CODE BEGIN 6 */
  311.   /* User can add his own implementation to report the file name and line number,
  312.     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  313.   /* USER CODE END 6 */

  314. }

  315. #endif

  316. /**
  317.   * @}
  318.   */

  319. /**
  320.   * @}
  321. */

  322. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
TIM1中断处理函数:
  1. /**
  2. * @brief This function handles TIM1 update interrupt.
  3. */
  4. void TIM1_UP_IRQHandler(void)
  5. {
  6.   /* USER CODE BEGIN TIM1_UP_IRQn 0 */

  7.   /* USER CODE END TIM1_UP_IRQn 0 */
  8.   HAL_TIM_IRQHandler(&htim1);
  9.   /* USER CODE BEGIN TIM1_UP_IRQn 1 */
  10.         //0-1开关,用于向电机发送脉冲,修改两次引脚电平后,减小节拍数(节拍数用于控制电机转动角度)
  11.         static int CNT = (int)0;
  12.         if(CNT == 1)
  13.         {
  14.                 CNT = 0;
  15.                 HAL_GPIO_WritePin(STEP_MOTOR_STEP_GPIO_PORT, STEP_MOTOR_STEP_GPIO_PIN, GPIO_PIN_SET);
  16.                 STEP_MOTOR_Msg.Step--;
  17.         }
  18.         else
  19.         {
  20.                 HAL_GPIO_WritePin(STEP_MOTOR_STEP_GPIO_PORT, STEP_MOTOR_STEP_GPIO_PIN, GPIO_PIN_RESET);
  21.                 BSP_STEP_MOTOR_Dir_Set(STEP_MOTOR_Msg.Dir); //设置电机转动方向
  22.                 BSP_STEP_MOTOR_MicroStep_Set(STEP_MOTOR_Msg.MicroStep);//设置电机细分数量级
  23.                 CNT++;
  24.         }
  25.         if(STEP_MOTOR_Msg.Step<=0)HAL_TIM_Base_Stop_IT(&htim1);//当节拍数为0时关闭定时器
  26.        
  27.   /* USER CODE END TIM1_UP_IRQn 1 */
  28. }


点赞  2016-9-1 12:23
引用: Tobey 发表于 2016-9-1 11:37
把APB1的频率升高后,ADS1248的初始化部分也会出问题,需要减少一个寄存器的写入操作,,不过初始化时往M ...

那就是SPI速率太高,看看手册的频率要求。
亚里士缺德
点赞  2016-9-1 12:42
引用: Tobey 发表于 2016-9-1 12:23
改为抢占式也是一样的结果,根据你说的TIM1的问题,刚刚测试了发现,如果将与TIM1相关的电机任务关闭的话 ...

看不出是什么原因造成的电机线程对打印的影响,其实我还是建议你不要用RTX,网上说RTX的bug比较多,毕竟不开源,有问题难以被反馈和解决,还是用UCOS或者自己写一个操作系统吧。。。。我自己写了一个tqOS也有bug但是我能自己修改不过。。。。
亚里士缺德
点赞  2016-9-1 13:11
引用: 汤权 发表于 2016-9-1 12:42
那就是SPI速率太高,看看手册的频率要求。

这个已经排除了,,手册上的上限是2MHz左右,140KHz完全没超啊~~
点赞  2016-9-1 13:29
引用: 汤权 发表于 2016-9-1 13:11
看不出是什么原因造成的电机线程对打印的影响,其实我还是建议你不要用RTX,网上说RTX的bug比较多,毕竟 ...

嗯,这是上面要求需要使用RTX的~~RTX在keil v4版本是是开源的,有提供源码的,,,不过我小白一个,不懂怎么找出问题的地方~~
点赞  2016-9-1 13:32
引用: Tobey 发表于 2016-9-1 13:32
嗯,这是上面要求需要使用RTX的~~RTX在keil v4版本是是开源的,有提供源码的,,,不过我小白一个,不 ...

啊,是么,我孤陋寡闻了,之前用过几次RTX,最大的优点就是不用移植,不用管很多移植上的细节。好吧,你们这个还需要好好弄,信号同步和资源竞争问题你最好液压考虑一下。我之前是遇到过很多次串口资源抢占问题。
亚里士缺德
点赞  2016-9-1 14:14
引用: 汤权 发表于 2016-9-1 14:14
啊,是么,我孤陋寡闻了,之前用过几次RTX,最大的优点就是不用移植,不用管很多移植上的细节。好 ...

你可能是在v5下用的CMSIS_RTOS吧,v5下把RTX经过封装后就没有源码了~~多谢提醒!到时候实在不行就换吧
点赞  2016-9-1 15:17
将任务printfTask略修改一下
int x = chanelDataArray[i];             // 增加这一句,C语言可能需要将定义移至函数的前面
R = x/8388607.0/8*2*810+180;  
printf("%5.2d ,  %4.2f  ;", x, R);
// 只要chanelDataArray[i]是整型,基本可以解决打印混乱的问题
// 请不要怀疑RTX
点赞  2016-9-6 16:08
引用: samos2011 发表于 2016-9-6 16:08
将任务printfTask略修改一下
int x = chanelDataArray;             // 增加这一句,C语言可能需要将定义移 ...

好的,多谢!
点赞  2016-9-14 15:52
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复