desarrollo embebido stm32

Resumen del lenguaje C (desarrollo integrado stm32)

Resumen de pequeños puntos de conocimiento del programa c

1. Uso de variable estática estática y variable externa extern

Dos formas de usar static variable static

1. Definir variables locales.

  1. El valor de la variable local declarada con static no desaparece después de que finaliza la llamada a la función y retiene el valor original, sino que ocupa el área de almacenamiento estático, por lo que la unidad de almacenamiento que ocupa no se libera. ¡Una aplicación típica es encontrar el factorial n con variables estáticas ! .
// 求阶乘 n!
int fac(int)
{
   static int f = 1 ;
   f = f * n ;
   return f ;
}
main()
{
   int i ,n  ;
   float sum;
   scanf("%d",&n) ;
   for(i = 1 ;i <= n ;i++)
   {
       sum = fac(i) ;
   }
   printf("输出%d!= %f ",n,sum)}

2. Las variables declaradas de esta manera se almacenan en la sección bss del programa y se inicializan a 0 cuando la sección bss se ejecuta en el programa .

// eg:
static int b[5] ;
//则b[0] = 0 ,b[1] = 0等等. 而如果不是这样定义则输出可能是乱码

2. Definición de variables globales
Cuando la definición de variables globales se limita a este archivo y no la utilizan otros archivos, puede agregar una declaración estática al definir variables externas. Tenga en cuenta que las variables externas agregadas con estática y sin agregar se almacenan en el área de almacenamiento estático, y la diferencia radica en la oración anterior " limitada al uso de este archivo ".

Variable externa externa

Rol : Declare una variable externa y expanda su alcance en el archivo del programa. Es decir, la variable global int A definida en el archivo 1 , puede definir extern A en el archivo 2 , puede llamar a la variable global en el archivo 1. Por ejemplo, en proyectos de ingeniería específicos reales, el tiempo variable global int32_t g_iRunTime definido en el archivo del temporizador puede representar hasta 24.85 días, que es el tiempo que su terminal puede funcionar continuamente. Si necesita llamarlo para juzgar el tiempo de ejecución, use extern g_iRunTime .

2. El método de valor de retorno después de la encapsulación de funciones

1. Solo devuelve un tiempo que valga la pena

  1. Un método común y simple es definir una función como una función con un valor de retorno, y el identificador de tipo de la función es consistente con el tipo de valor de retorno.
    Por ejemplo, int fun () ; la función devuelve un valor numérico de tipo int .
  2. Defina una variable global, porque la variable global existe en el área de almacenamiento estático, cuando se llama a la función, se cambia el valor de la variable global y también se realiza la función de devolver la función.

2. Solicitud de devolución de varias veces la pena

  1. Los dos primeros devuelven un método valioso que se puede compartir para devolver múltiples valores.
  2. Defina una matriz o puntero en el parámetro formal y defina una matriz en la función principal para guardar el valor devuelto , como el siguiente código:
// 函数fun返回了三个值,通过return1个,和数组s[2]两个,以达到要求
int fun(int str[2]);
main()
{
    int s[2] ;//定义一个数组来存放fun函数的返回的a  b 之间最大值,最小值
    scantf("%d%d",&a,&b);
    if(fun(a,b,s))
    {
        printf("大的%d,小的%d",a[0],a[1]);
    }
    else 
        printf("相等");    
}
int fun(int a ,int b ,int str[2])
{
    if(a > b)
    {
        str[0] = a ;
        str[1] = b ;
    return 1 ;
    }
    if(a < b)
    {
        str[0] = b ;
        str[1] = a ;
        return 1 ;
    }
    else
    return 0 ;
}

Cabe señalar que el principio general: en el diseño del programa, al subdividir el módulo, se requiere que el módulo tenga una " cohesión " fuerte y un acoplamiento débil con otros módulos . El simple entendimiento es que cada función en el paquete tiene su propia función independiente, es decir, una sola función, que es conveniente llamar, pero no demasiado desordenada. Restrinja el uso de variables globales .

3. La diferencia entre el control del ciclo continúa y se rompe

En ingeniería de proyectos, o en código simple de lenguaje C, la circulación es muy común y es muy importante dominar las diversas formas de circulación. Aquí hay una breve introducción a la diferencia entre continuar y romper el control de circulación .
Use el código para reflejar:

//简介循环控制continue与break的区别
main()
{
    while(表达式一)
    {
        if(表达式二)
        {
            break ; //跳出循环,也即跳出while语句转执行下面的语句
        }
    } 
    while(表达式一)
    {
        if(表达式二)
        {
            continue ; //跳到条件限制,也即跳到while语句判断中
        }
    }
}

Como lo anterior es claro y fácil de entender, al escribir el código o comprender el código fuente descargado, si no es mientras (1) aparece en la función principal principal, mientras que otras funciones aparecen mientras (1), debe haber una declaración de interrupción Esto es más importante en la tarea de aprender a comprender el código fuente primero. (Parece que esto solo es adecuado para principiantes, siempre que tenga algo de experiencia, conocerá estos puntos de conocimiento obvios pero clave)

Especificación del procedimiento del proyecto

1. Cola de mensajes FIFO

La idea central : a través del mecanismo de la cola de mensajes, en la función PRINCIPAL, a través de la tarea de entrega de mensajes a realizar. Cuando se necesita ejecutar una tarea, se notifica la cola de mensajes y el programa principal la ejecuta. El programa principal analiza la cola de mensajes en la función para ver si hay alguna tarea .

  1. Primero defina el tipo de cola y el tamaño de la cola de mensajes en el archivo de encabezado.
typedef struct
             {
                uint8_t *MsgRam;	 /*队列缓存*/						 
				uint8_t MsgSize;   /*队列大小*/ 
				uint8_t MsgCount;  /*收到的新消息个数*/
				uint8_t MsgWritePoint;  /*写指针*/
				uint8_t MsgReadPoint;  /*读指针*/
			}Msg_Fifo;
#define TaskSize   (100)   /*消息队列尺寸*/	
  1. Tipo de mensaje definido por un tipo de enumeración enum
typedef enum
           {
              Idletask = 0....            //消息类型,根据项目中的各个需要Cpu处理的模块决定
           }
  1. Inicializar la estructura de la cola.
void bsp_Init_Msg_Fifo(void)
{
  _MsgTask.MsgSize = TaskSize; 
	_MsgTask.MsgRam =  _MsgRam;  /*队列缓存*/
   _MsgTask.MsgCount = 0;       /*新数据个数*/
   _MsgTask.MsgReadPoint = 0;   /*读指针*/
   _MsgTask.MsgWritePoint = 0;  /*写指针*/
}
  1. Cree una función: uint8_t MsgtGetMes (Msg_List * _pByte) para leer un mensaje de la cola de mensajes. Y una función: uint8_t MsgtPushMes (Msg_List * _pByte), escribe un mensaje en la cola.
  2. Determine si hay una tarea que ejecutar (esta vez necesita usar un temporizador de software (descrito en detalle a continuación), cada función está configurada en un cierto tiempo para enviar datos de procesamiento a la CPU), coloque las tareas a ejecutar en la función de cola void AppTaskScan (void ), Tarea de inspección.
  3. Cree una función: vTaskStartScheduler (), función de programación de tareas, lea una tarea de la cola de mensajes para ejecutar, la tarea que señala primero se ejecuta primero, si hay una tarea que activa la misma tarea al mismo tiempo, se ejecutará de acuerdo con el orden de la cola .

** Hasta ahora , ** En la función principal mian while (1), llame a 5, 6 dos funciones para verificar.

El uso de la cola FIFO es principalmente para la gestión de la asignación de CPU: un sistema informático general tiene solo una CPU. Si varios procesos en el sistema cumplen las condiciones de funcionamiento, esto se puede gestionar con una cola lista. Cuando se necesita ejecutar un proceso, su nombre de proceso se inserta al final de la cola lista. Si la cola está vacía, la CPU ejecuta el proceso de inmediato; si la cola no está vacía, el proceso debe esperar al final de la cola. La CPU siempre ejecuta primero el proceso en la parte superior de la cola. Después de que se asigna un cierto período de tiempo para un proceso, se inserta en la cola de la cola y espera. La CPU gira para servir el siguiente proceso que aparece en la parte superior del equipo. Entonces Continúe de acuerdo con el principio de "FIFO" hasta que el proceso ejecutado se elimine de la cola.

La cola quince también se puede utilizar en muchos escenarios, como el puerto serie quince, la distribución cuando se ejecutan varios puertos serie.

2. Uso de temporizadores de software.

Esta parte la uso principalmente para el programa stm32, primero configuro el temporizador systick como el temporizador de tic del sistema. El período de tiempo predeterminado es de 1 ms. Se implementan varios temporizadores de software para el programa principal (precisión de 1 ms), y la cantidad de temporizadores de software se puede aumentar o disminuir modificando TMR_COUNT.

Esta parte es principalmente para que la CPU se ocupe del uso de la información de la cola . Establezca un temporizador para cada tarea. Una vez que se alcanza el tiempo establecido, es como escribir un mensaje de tarea en la cola hasta que la CPU lo procese. El temporizador implementa principalmente la programación de tareas. ¡Por supuesto, los ingenieros con diferentes estilos tienen diferentes usos!

  1. Configure el temporizador systick con un período de 1 ms
    . En core_cm3.h, hay una función uint32_t SysTick_Config (uint32_t ticks). El parámetro formal de esta función indica cuántos ciclos del reloj central para activar una interrupción del temporizador
    Systick -SystemCoreClock / 1000 indica la frecuencia de temporización 1000
    Hz , es decir, el período de tiempo es 1 ms -SystemCoreClock / 500 significa que la frecuencia de tiempo es 500Hz, es decir, el período de tiempo es 2ms
    -SystemCoreClock / 2000 significa que la frecuencia de tiempo es 2000Hz, es decir, el período de tiempo es 500us,
    por lo que generalmente en la función de inicialización del temporizador Llame a SysTick_Config (SystemCoreClock / 1000); forme una función de interrupción periódica para ejecutar la interrupción una vez cada ms, es decir, si necesita interrumpir, debe escribir un programa de servicio de interrupción void SysTick_Handler (void); esta función es principalmente para el siguiente desarrollo del conteo de temporizador de software 1 ms menos una operación.

  2. Configuración del temporizador de software
    1. Defina la estructura del temporizador y el número de temporizadores y el nombre de cada temporizador de tarea

 typedef struct
{
	volatile uint8_t Flag;		/* 定时到达标志  */
	volatile uint32_t Count;	/* 计数器 */
	volatile uint32_t PreLoad;	/* 计数器预装值 */
}SOFT_TMR;
/* 软件定时器个数 */
#define TMR_COUNT          5   //自己设定需要多少软件定时器
/*定义定时器名称*/
#define C_TMR_ID           (4)  
#define C_TMR_ID           (3)
#define E1_TMR_ID          (2)
#define E_TMR_ID           (1)
#define cTMR_ID            (0)
  1. Ahora escribimos principalmente dos funciones: void bsp_StartAutoTimer (uint8_t _id, uint32_t _period) es principalmente para cargar el período de valor inicial del contador en tiempo real establecido en la estructura, y usar el programa de servicio de interrupción del temporizador para disminuir uno y reducirlo a En 0, el indicador se establece en 1. En otra función uint8_t bsp_CheckTimer (uint8_t _id), se juzga si el indicador de llegada de temporización del indicador está activado y devuelve 1. Se utiliza para la tarea de inspección de AppTaskScan (vacío) vacía.

Resumen: Este artículo es principalmente un resumen basado en mi propio estudio. Soy un novato y estoy muy feliz de compartir los resultados del aprendizaje. ¡Este artículo espera ayudar a los lectores a resumir y grabar para mí!

Publicado 2 artículos originales · elogiado 3 · visitas 163

Supongo que te gusta

Origin blog.csdn.net/peipanbryant/article/details/105610240
Recomendado
Clasificación