stm32 single timer simulates an indefinite number of analog timers

Article catalog

preface

I Basic data structure?

2, Create a list C piece

1. Initialize the header node

2. Adding linked list nodes

3. Delete, search and print linked list nodes

III Object oriented thinking

Improved code

Add the remaining code

IV realization

V effect

summary

Tip: after the article is written, the directory can be generated automatically. Please refer to the help document on the right for how to generate it

preface

Purpose: generate multiple frequency divisions through a timer. For example, analog timers A and a have name, input, output, aim, now, task pointer and other information. When an interrupt comes, if input==1, the current value now increases automatically, and when now==aim, output=1 is generated. The simulated timer is hung on the linked list and can be deleted at any time.

Tip: the following is the main content of this article. The following cases can be used for reference

I Basic data structure?

The first is the structure diagram of the timer

Then is the structure diagram of nodes and linked lists

code implementation

typedef struct Tcreate
{
	u32 now ;
	u32 aim;               //0-65535
	u8 input;               
	u8 output;            
	u8 num;               //Up to 256
	void(*task)(void);                        //The return value is void, and the entry parameter is a function pointer of void type

}timepack;               //Timer data structure 16 bytes Memory problems

Where num stands for name or priority.

And the structure of linked list nodes

typedef struct Node
{
  timepack *data_point;
  struct Node *next;
}Time_node;              //Timer node

2, Create a list C piece

1. Initialize the header node

Time_node *headnode=NULL;                       
                                          
bool headnode_init()                       //Node initialization
{
	headnode=(Time_node*)malloc(sizeof(Time_node));//Request memory
	if(headnode==NULL)return false;
	headnode->next=NULL;
	return true;
}

2. Adding linked list nodes

Traverse the linked list until it points to null, apply for memory of timenode and memory of timepack.

copy the data indicated by the pointer of the tiamepack to the area indicated by the pointer in the data field of the new node. (compare winding)

							
bool add_timer(timepack *data)                  //Add frequency division clock
{
	Time_node *p=headnode;                        
	while(p->next!=NULL)                          //Traverse until the pointer field of p points to NULL
	{
		p=p->next;
	}
	p->next=(Time_node*)malloc(sizeof(Time_node));//Request node memory
	if(p->next==NULL)return false;
	p=p->next;
	p->data_point=(timepack*)malloc(sizeof(timepack));//Request node packet memory
	if(p->data_point==NULL)
	{
		free(p);                                     //Release the space opened up
		return false;
	}
	memcpy(p->data_point,data,sizeof(timepack));
	p->next=NULL;
	return true;
}

3. Delete, search and print linked list nodes

bool delete_timer(u8 name)              //Delete node number name
{
	bool res=false;
	Time_node *p=headnode;
	while(p->next!=NULL)
	{
		Time_node *Temp=p;
		p=p->next;	
		if(p->data_point->num==name)
		{
			Temp->next=p->next;
			free(p->data_point);           //Release the memory pointed by the pointer and the memory pointed by p in the data field pointed by p
			p->data_point=NULL;                //Avoid generating wild pointers
			free(p);
			p=Temp;                         
			res=true;
		}
	}
	return res;
}

Find the function. Note that the return value is the data of a node pointer type

Time_node* search_timer(u8 name)        //Find the pointer of the node corresponding to name
{                                       //You can access the data of the corresponding name
	Time_node *p=headnode;
	while((p->next!=NULL)&&(p->data_point->num!=name))
	{
		p=p->next;
	}
	if(p->data_point->num!=name)p=NULL;    //Determine whether name exists
  return p;
}
u8 print_all()                        //Traverse and print all nodes and get the total number of nodes
{
	u8 i=0;
	Time_node*p=headnode;
	printf("------------begin----------------");
	printf("\r\n");	
	while(p->next!=NULL)
	{
		p=p->next;
		i++;
		printf("i=%d\r\n",i);
		printf("aim=%d\r\n",p->data_point->aim);
		printf("num=%d\r\n",p->data_point->num);		
	
	}
	printf("-------------end--------------");
	printf("\r\n");
	return i;
}

III Object oriented thinking

I didn't have the consciousness of process and object at all before. I know that after reading the list explanation of station B up, I really have a feeling of enlightenment https://www.bilibili.com/video/BV1BE411h7kG?share_source=copy_web

Improved code

Perform task operations on all nodes after the current node. The task is set by itself, such as the data set as the printf node. Then traverlist is a print function, the same as the printf all function above. But! We can set the task to other (such as oled display), so traverlist can display all nodes after the current one. There is no need to write a show all function, which is very convenient.

//The entry parameter points to the pointer of the current node, and the entry parameter with null return value is the function pointer of the node pointer
void  traverlist(Time_node *nowpoint,void(*task)(Time_node *point))
{
	Time_node *ptemp=nowpoint;
	while(ptemp!=NULL)
	{
		task(ptemp);
		ptemp=ptemp->next;
	}
}

Add the remaining code

//The priority is in the order of name's size. The card with the smaller name is in the front	
bool add_timer2(timepack *data)
{
	Time_node *p=headnode;
	Time_node *temp;
	while((p->next->data_point->num<=data->num)&&(p->next!=NULL))                       
	{
		p=p->next;
	}
	temp=p->next;
	p->next=(Time_node*)malloc(sizeof(Time_node));//Request node memory
	if(p->next==NULL)return false;
	p=p->next;
	p->data_point=(timepack*)malloc(sizeof(timepack));//Request node data structure memory
	if(p->data_point==NULL)
	{
		free(p);                                     //Release the space opened up
		return false;
	}
	memcpy(p->data_point,data,sizeof(timepack));
	p->next=temp;
	return true;
}

Finally, learn the stm32 library function and encapsulate it.

//Mode 0 in order 1 by name from small to large priority from high to low
void include_time(u32 Now,u32 Aim,u8 Num,void(*work)(void),u8 mode)   //encapsulation
{
	timepack timestruct;
	timestruct.aim=Aim;
	timestruct.now=Now;
	timestruct.num=Num;
	timestruct.input=1;
	timestruct.output=0;
	timestruct.task=work;
	if(mode==0)add_timer(&timestruct);  
  else add_timer2(&timestruct);          
}

IV realization

Timer III is adopted

void TIM3_IRQHandler(void)   //TIM3 interrupt
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //Check whether the specified TIM interrupt occurs: TIM interrupt source 
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //Clear the interrupt pending bit of TIMx: TIM interrupt source 
	
			time_handle();

		}
}
void time_handle()                        //timer interrupt 
{
	Time_node *p=headnode;                  //Define header pointer
	p=p->next;
	while(p)
	{		
		if((p->data_point->input==1)&&(p->data_point->output==0))//out is equivalent to the interrupt flag bit
		{
			p->data_point->now++;
			if(p->data_point->now>=p->data_point->aim)//Timer overflow 
			{
				p->data_point->output=1;          
				p->data_point->now=0;             //How to generate an interrupt?
				deal_task(p);
			}
		}
		else if(p->data_point->input==0)delete_timer(p->data_point->num);
		
		p=p->next;
	}
}
//Timer processing task
void  deal_task(Time_node *point)
{
	if(point->data_point->output==1)
	{
		point->data_point->task();             //implement
		point->data_point->output=0;
	}
}
void timer_init()
{
	include_time(0,100,36,work36,0);  
  include_time(0,200,37,work37,0); 
	include_time(0,300,22,work22,0); 
	include_time(0,400,24,work24,0); 	
	include_time(0,10,44,work44,0);       //include encapsulation function
	include_time(0,500,11,work11,1);
}

work randomly sets up a few time-consuming tasks because they are carried out in interruption....

int main(void)
{ 
  int a,b,len;
	Time_node* datapack;
	delay_init();	    	 //Delay function initialization	  
	uart_init(9600);	 	//The serial port is initialized to 9600
	LED_Init();		  		//Initialize the hardware interface to the LED
 	LCD_Init();
	
	headnode_init();     //Global first node initialization
	timer_init();        //Be sure to put it behind the first node
	
	POINT_COLOR=RED; 
	LCD_Clear(WHITE);
	TIM3_Int_Init(500,7200);                     //Total clock timer 0.05s
	POINT_COLOR=RED;	  
	LCD_ShowString(30,20,200,24,24,"Mini STM32 ^_^");	
	delete_timer(22);             //Delete specified name	
		while(1) 
	{				
		a=sizeof(timepack);    //Data byte length
		LCD_ShowNum(30,60,a,2,24);
		b=sizeof(Time_node);    //Node byte length
		LCD_ShowNum(60,60,b,2,24);
//		len=print_all();              // Print all data
		
		datapack=search_timer(24);            //Find the address of the corresponding node of the data with the specified name
		LCD_ShowNum(30,140,search_timer(36)->data_point->now,3,24);
		LCD_ShowNum(100,140,search_timer(36)->data_point->aim,3,24);
		LCD_ShowNum(170,140,search_timer(36)->data_point->output,3,24);

		LCD_ShowNum(30,180,search_timer(37)->data_point->now,3,24);		
		LCD_ShowNum(100,180,search_timer(37)->data_point->aim,3,24);
		LCD_ShowNum(170,180,search_timer(37)->data_point->output,3,24);
		
		LCD_ShowNum(30,220,datapack->data_point->now,3,24);
		LCD_ShowNum(100,220,datapack->data_point->aim,3,24);
		LCD_ShowNum(170,220,datapack->data_point->output,3,24);

		LCD_ShowNum(30,260,search_timer(11)->data_point->now,3,24);		
		LCD_ShowNum(100,260,search_timer(11)->data_point->aim,3,24);
		LCD_ShowNum(170,260,search_timer(11)->data_point->output,3,24);

	  traverlist(search_timer(11),showdata);   //Traverse the nodes after the current node and execute the showdata function
	} 
}

V effect

I've seen RTOS in recent days. I plan not to execute tasks in interrupts, but in the main function. Interrupts only select the one with the highest priority, which means scheduling.

summary

I've seen RTOS in recent days. I plan not to execute tasks in interrupts, but in the main function. Interrupts only select the one with the highest priority, which means scheduling.

Tags: Singly Linked List stm32

Posted by e39m5 on Mon, 20 Dec 2021 16:49:56 +1030