目录
1.RTT系统启动
RTT系统将main函数重定义在$Sub$$main(void)中,即程序运行顺序如下:
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
int $Sub$$main(void)
{
rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
int rtthread_startup(void)
{
rt_hw_interrupt_disable();
/* board level initialization
* NOTE: please initialize heap inside board initialization.
*/
rt_hw_board_init();
/* show RT-Thread version */
rt_show_version();
/* timer system initialization */
rt_system_timer_init();
/* scheduler system initialization */
rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
/* signal system initialization */
rt_system_signal_init();
#endif
/* create init_thread */
rt_application_init();
/* timer thread initialization */
rt_system_timer_thread_init();
/* idle thread initialization */
rt_thread_idle_init();
/* start scheduler */
rt_system_scheduler_start();
/* never reach here */
return 0;
}
rtthread_startup函数中 rt_hw_board_init()在boardc中,是对板子硬件的初始化,程序如下
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#define STM32_SRAM_SIZE 64
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
void rt_hw_board_init()
{
/* System Clock Update */
RCC_Configuration();
GPIO_InitTypeDef gpioInit;
//打开GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);
//LED上拉连接GPIOB 12引脚,所以设置如下,推挽输出,Pin12,2MHz输出速度
gpioInit.GPIO_Mode=GPIO_Mode_Out_PP;
gpioInit.GPIO_Pin=GPIO_Pin_5;
gpioInit.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&gpioInit);
GPIO_Init(GPIOE,&gpioInit);
gpioInit.GPIO_Mode=GPIO_Mode_Out_PP;
gpioInit.GPIO_Pin=GPIO_Pin_12;
gpioInit.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&gpioInit);
/* System Tick Configuration */
_SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND) ;
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
//rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
rt_system_heap_init(HEAP_BEGIN, (void *)STM32_SRAM_END);
#endif
}
其中rt_system_heap_init(HEAP_BEGIN, (void *)STM32_SRAM_END)是对堆heap的初始化,HEAP_BEGIN是从
Image$$RW_IRAM1$$ZI$$Limit
开始,到指定大小后结束。
然后回到rtthread_startup()对RTT系统定时器,调度器,信号量等功能初始化,再调用rt_application_init()创建main()进程以回到用户自己的main()中,后面开启调度器,进入main()函数中。rt_application_init()程序如下:
oid rt_application_init(void)
{
rt_thread_t tid;
#ifdef RT_USING_HEAP
tid = rt_thread_create("main", main_thread_entry, RT_NULL,
RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(tid != RT_NULL);
#else
rt_err_t result;
tid = &main_thread;
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
/* if not define RT_USING_HEAP, using to eliminate the warning */
(void)result;
#endif
rt_thread_startup(tid);
}
2.创建自己的进程
在main()可以先对模块功能初始化,然后创建进程。main()函数运行完自己会把自己(注销?)挂起,反正不会运行自己了。程序如下:
/***************************************************************************************
备注:
*
***************************************************************************************/
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "w5500.h"
#include "24c02.h"
#include "spi.h"
#include "cd4051.h"
#include "adc.h"
#include "bsp_485.h"
#include "ioinput.h"
#include <string.h>
#include "led.h"
#include "oled.h"
#include "HT16K33.h"
#include "display.h"
#include "bsp_adc.h"
#include "pt100.h"
#include <stdbool.h>
#include "rtthread.h"
//#include "application.h"
extern float Tem[8];
extern u8 number[20];
extern unsigned char Read_W5500_1Byte(unsigned short reg);
u8 flag_usart =0 ; //串口1接收标志位
u8 key[6];
extern __IO uint16_t ADC_ConvertedValue[4];
float ADC_ConvertedValueLocal[4];
void AD2(void);
void VibAndTem(void);
static rt_thread_t thread1=RT_NULL;
static rt_thread_t thread2=RT_NULL;
static rt_thread_t thread3=RT_NULL;
static rt_thread_t thread4=RT_NULL;
static rt_thread_t thread5=RT_NULL;
static rt_thread_t thread6=RT_NULL;
static void thread1_entry (void *parameter);
static void thread2_entry (void *parameter);
static void thread3_entry (void *parameter);
static void thread4_entry (void *parameter);
static void thread5_entry (void *parameter);
static void thread6_entry (void *parameter);
/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_timer_t timer2;
u8 cnt;
u8 Y_num[8];
u8 R_num[8];
/* 定时器1超时函数 */
static void timeout1(void *parameter)
{
// if ( thread3 != RT_NULL)
rt_thread_resume (thread3);
rt_schedule();
/* 运行第10次,停止周期定时器 */
/* if (cnt++ >= 9)
{
rt_timer_stop(timer1);
rt_kprintf("periodic timer was stopped! \n");
}
*/
}
/* 定时器2超时函数 */
static void timeout2(void *parameter)
{
rt_thread_resume (thread6);
rt_schedule();
}
int timer_sample(void)
{
/* 创建定时器1 周期定时器 */
timer1 = rt_timer_create("timer1", timeout1,
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer1 != RT_NULL)
rt_timer_start(timer1);
/* 创建定时器2 周期定时器 */
timer2 = rt_timer_create("timer2", timeout2,
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer2 != RT_NULL)
// rt_timer_start(timer2);
return 0;
}
static void thread1_entry(void* parameter)
{
while(1)
WEB();
}
static void thread2_entry(void* parameter)
{
while(1){
//点亮LED
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
//延时0.5s
rt_thread_delay(RT_TICK_PER_SECOND);
//关闭LED
GPIO_SetBits(GPIOB,GPIO_Pin_12);
//延时0.5s
rt_thread_delay(RT_TICK_PER_SECOND);
cnt++;
// analogArry[1]=cnt;
// Tem[0]=(float)cnt;
}
}
static void thread3_entry(void* parameter)
{
while(1)
{
VibAndTem();
DISPLAYfloat(Tem[0],Tem[1],Tem[2],Tem[3],Tem[4],Tem[5],Tem[6],Tem[7]);
rt_thread_suspend(thread3);
rt_thread_resume (thread6);
rt_schedule();
}
}
static void thread4_entry(void* parameter)
{
while(1){
AD();
}
}
static void thread5_entry(void* parameter)
{
while(1){
AD2();
}
}
static void thread6_entry(void* parameter)
{
while(1)
{
u8 y_num[8]={1,1,1,1};
u8 r_num[8]={0,0,0,0,1,1,1,1};
display_led(y_num,r_num);
rt_thread_suspend(thread6);
rt_schedule();
}
}
int rt_application_init1()
{
thread1 = rt_thread_create("thread1",
thread1_entry,
RT_NULL,
512, 10, 10);
if (thread1 != RT_NULL)
rt_thread_startup(thread1);
//进程2初始化
thread2 = rt_thread_create("thread2",
thread2_entry,
RT_NULL,
512, 10, 10);
if ( thread2 != RT_NULL)
rt_thread_startup(thread2);
//进程3初始化
thread3 = rt_thread_create("thread3",
thread3_entry,
RT_NULL,
1024, 8, 20);
if ( thread3 != RT_NULL)
rt_thread_startup(thread3);
//进程4初始化
thread4 = rt_thread_create("thread4",
thread4_entry,
RT_NULL,
1024, 10, 10);
if ( thread4 != RT_NULL)
rt_thread_startup(thread4);
//进程5初始化
thread5 = rt_thread_create("thread5",
thread5_entry,
RT_NULL,
512, 10, 10);
if ( thread5 != RT_NULL)
rt_thread_startup(thread5);
thread6 = rt_thread_create("thread6",
thread6_entry,
RT_NULL,
512, 7, 10);
if ( thread6 != RT_NULL)
rt_thread_startup(thread6);
return 0;
}
/*******************************************************************************
* 函数名 : main
* 描述 : 主函数,用户程序从main函数开始运行
* 输入 : 无
* 输出 : 无
* 返回值 : 无
* 说明 : 无
*******************************************************************************/
int main(void)
{
I2C_INIT(); //IIC初始化
uart_lora_init();
Load_Net_Parameters(); //装载网络参数
System_Initialization(); //STM32系统初始化函数(初始化STM32时钟及外设)
W5500_Hardware_Reset(); //硬件复位W5500
W5500_Initialization(); //W5500初始货配置
InitCD4051(); //4051初始化
bsp_InitSPIBus(); //SPI初始化
InitTM7705(); //ADC初始化
TM7705_CalibSelf(1); /*自校准,?180ms */
TM7705_CalibSelf(2); /*自校准,?180ms */
//Lora_config();
ADC1_Init();
DISPLAY_INIT();
rt_application_init1();
timer_sample();
rt_schedule();
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Io_Init();//IO初始化
// RFS_GPIO_init();//恢复出厂设置按键初始化函数
//Modbus_Init();//modbus初始化
//RS485_Init();//测试
TIM4_Init();
// Timer5_enable(99);
//while(1)
//{
// //AD();
// VibAndTem();
// //AD2();
// //DISPLAY(1,2,3,4,5,6,7,8);
//
//}
//
}
void VibAndTem(void)
{
uint16_t Tem_ADC[6];
float V1,V2,R1,R2;
//AD();
Tem_ADC[0]=(analogArry[0]<<8)|analogArry[1];
Tem_ADC[1]=(analogArry[2]<<8)|analogArry[3];
Tem_ADC[2]=(analogArry[4]<<8)|analogArry[5];
Tem_ADC[3]=(analogArry[6]<<8)|analogArry[7];
Tem_ADC[4]=(analogArry[8]<<8)|analogArry[9];
Tem_ADC[5]=(analogArry[10]<<8)|analogArry[11];
V1 =(float) (Tem_ADC[4])/65535*2.5/51;
V2 =(float) (Tem_ADC[5])/65535*2.5/51;
R1=(V1*14000+2000)/(20-V1*7);
R2=(V2*14000+2000)/(20-V2*7);
//Tem[4]=CalculateTemperature(R1);
// Tem[5]=CalculateTemperature(R2);
Tem[0]=(float) (Tem_ADC[0])/65535*1000/50;
Tem[1]=(float) (Tem_ADC[1])/65535*1000/50;
Tem[2]=(float) (Tem_ADC[2])/65535*1000/50;
Tem[3]=(float) (Tem_ADC[3])/65535*1000/50;
}
void AD2(void)
{ u8 i;
uint16_t My_ADC[4][30];
for(i=0;i<30;i++)
{
My_ADC[0][i]=ADC_ConvertedValue[0];
My_ADC[1][i]=ADC_ConvertedValue[1];
My_ADC[2][i]=ADC_ConvertedValue[2];
My_ADC[3][i]=ADC_ConvertedValue[3];
}
ADC_ConvertedValueLocal[0] =(float) GetDelExtremeAndAverage(My_ADC[0],30,5,5)/4096*3;
ADC_ConvertedValueLocal[1] =(float) GetDelExtremeAndAverage(My_ADC[1],30,5,5)/4096*3;
ADC_ConvertedValueLocal[2] =(float) GetDelExtremeAndAverage(My_ADC[2],30,5,5)/4096*3;
ADC_ConvertedValueLocal[3] =(float) GetDelExtremeAndAverage(My_ADC[3],30,5,5)/4096*3;
}
在这个程序中创建了两个定时器,6个线程。定时器2暂时没用,定时器1用于启动线程3进行数码管扫描;进程1进行网络通讯;进程2控制继电器;进程3进行计算和显示;进程4进行AD7705读取;进程5进行STM32自带AD读取;进程6进行LED灯显示。其中,LED灯显示与数码管显示冲突,两个进程不可以同时运行,因此让进程3调度进程6。