STM32 Free RTOS实战

2023-05-16

FreeRTOS是一个开源的实时操作系统。

使用的平台:秉火STM32 Cortex-M3内核开发板,Free RTOS v8.2.3。

多任务流水灯

.
├── Doc
│   └── readme.txt
├── FreeRTOS      //OS依赖目录
│   ├── inc
│   │   ├── croutine.h
│   │   ├── ...   //头文件
│   └── src
│       ├── croutine.c
│       ├── ...   //源码文件
├── Libraries     //库文件
├── Project       //工程文件
└── User
    ├── led
    │   ├── bsp_led.c
    │   └── bsp_led.h
    ├── main.c    //源码
    ├── stm32f10x_conf.h
    ├── stm32f10x_it.c
    └── stm32f10x_it.h

创建多任务:

int main ( void )
{	
	xTaskCreate( vTaskStart, "Task Start", 512, NULL, 1, NULL );
    vTaskStartScheduler();
}

void vTaskStart( void * pvParameters )
{
	LED_Init ();

	xTaskCreate( vTaskLed1, "Task Led1", 512, NULL, 1, NULL );
	xTaskCreate( vTaskLed2, "Task Led2", 512, NULL, 1, NULL );
	xTaskCreate( vTaskLed3, "Task Led3", 512, NULL, 1, NULL );

	vTaskDelete( NULL );	
}

void vTaskLed1( void * pvParameters )
{
	while(1)
	{
		macLED1_ON ();			 
		vTaskDelay( 1000 );
		macLED1_OFF ();	
		vTaskDelay( 1000 );
	}
}

上面依次对应主函数创建一个任务并开始调度,任务中又新建了三个任务,每个任务负责一个灯的开启和关闭。

任务管理-挂起与恢复

static void vTaskLed1( void * pvParameters ) //LED闪烁任务,循环执行
{
	TickType_t xLastWakeTime;	
	while(1)                                                    
	{
		macLED1_ON ();			                                     
		vTaskDelayUntil(&xLastWakeTime, 200 / portTICK_RATE_MS); 
		macLED1_OFF ();		                                       	
		vTaskDelayUntil(&xLastWakeTime, 200 / portTICK_RATE_MS);
	}
	
}


static void vTaskKey( void * pvParameters )   //按键控制挂起或恢复任务
{
	uint8_t ucKey1Press = 0, ucKey2Press = 0;	
	while(1)
	{
		if( Key_Scan ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1, & ucKey1Press ) )      //KEY1按下,任务挂起
		{			
			vTaskSuspend( xHandleTaskLed1 );                                           
		}
		else if( Key_Scan ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1, & ucKey2Press )) //KEY2按下,任务恢复
		{		
			vTaskResume( xHandleTaskLed1 );                                          
		}
		vTaskDelay( 20 / portTICK_RATE_MS );                                         
	}
}

现象:开机闪烁,按下按键1将停止,按下按键2恢复。

消息队列

/************************************ 创建队列 *********************************/
static xQueueHandle xQueue;

/********************************** 任务函数声明 *******************************/
static void vTaskStart  ( void * pvParameters );
static void vTaskSender ( void * pvParameters );
static void vTaskReceive( void * pvParameters );

/********************************** 任务函数定义 *******************************/
static void vTaskStart( void * pvParameters )                            //起始任务
{
	LED_Init ();	     //初始化LED
	USARTx_Config ();   //初始化串口
	printf("Test Queue");

	/* 创建消息队列 */
	xQueue = xQueueCreate(5, sizeof(uint32_t) );
	if(xQueue != NULL)                                                      //创建成功则创建另外两个任务
	{
		/* 创建发送1和发送2任务 */
		xTaskCreate( vTaskSender, "Task Sender1", 512, ( void *)100, 1, NULL);  //传递的参数为向队列中添加的参数
		xTaskCreate( vTaskSender, "Task Sender2", 512, ( void *)200, 1, NULL);
		
		/* 创建接收任务 */
		xTaskCreate( vTaskReceive, "Task Receiver", 512, NULL, 2, NULL );
	}	
	else                                                                      //创建失败
	{
		while(1);
	}
	vTaskDelete( NULL );                                                      //删除
}
static void vTaskSender( void * pvParameters )
{
	uint32_t lValueToSend;
	portBASE_TYPE xStatus;

	lValueToSend = ( uint32_t ) pvParameters;                  //获取参数(地址传递)
	while(1)
	{
		xStatus = xQueueSendToBack( xQueue, &lValueToSend, 0 );  //阻塞写入队列	
		if( xStatus != pdPASS )                                  
		{
		  printf("数据不能发送到数据队列\r\n");
		}	
		taskYIELD();                                             //放弃时间片,让出CPU
	}
}
static void vTaskReceive( void * pvParameters )
{
	uint32_t lReceivedValue;
	portBASE_TYPE xStatus;

	while(1)
	{
		xStatus = xQueueReceive( xQueue, &lReceivedValue, portMAX_DELAY );//阻塞读取
		if(xStatus==pdPASS)                                           
		{
			printf( "接收的数据是: %d\r\n", lReceivedValue );               
		}
		else                                                            
		{
			printf("没有接收的消息.\r\n");
		}
	}
}
/************************************* 主函数 **********************************/
int main ( void )
{	
	xTaskCreate( vTaskStart, "Task Start", 512, NULL, 1, NULL );       
	vTaskStartScheduler(); 
}

输出结果:

二值信号量–同步数据读写

static SemaphoreHandle_t  xSemaphore = NULL;
xSemaphore = xSemaphoreCreateBinary();
//发送信号量
xSemaphoreGive( xSemaphore );
//接收信号量
xSemaphoreTake( xSemaphore, portMAX_DELAY );

计数信号量

xSemaphore = xSemaphoreCreateCounting(5, 5);  //总共5个停车位,目前有5个可用(计数初值为5)

static void vTaskKey1( void * pvParameters ) 
{
	BaseType_t xResult;
	uint8_t ucKey1Press = 0;
	while(1)
	{
		if( Key_Scan ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1, & ucKey1Press ) ) 
		{
            xResult = xSemaphoreTake( xSemaphore,0);    //接收信号量,信号值减1                  
            taskENTER_CRITICAL();
            if ( xResult == pdPASS )                      
                printf ( "\r\nKEY1被单击:成功申请到停车位。\r\n" );
            else
                printf ( "\r\nKEY1被单击:不好意思,现在停车场已满!\r\n" );
            taskEXIT_CRITICAL();
		}
		vTaskDelay( 20 / portTICK_RATE_MS );  
	}
	
}

static void vTaskKey2( void * pvParameters ) 
{
	BaseType_t xResult;
	uint8_t ucKey2Press = 0;
	while(1)
	{
		if( Key_Scan ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1, & ucKey2Press ) ) 
		{
			xResult = xSemaphoreGive( xSemaphore );    //发送信号量,信号值加1
			taskENTER_CRITICAL();
			if ( xResult == pdPASS ) 
				printf ( "\r\nKEY2被单击:释放1个停车位。\r\n" );	
		    else
			    printf ( "\r\nKEY2被单击:但已无车位可以释放!\r\n" );
			taskEXIT_CRITICAL();
		}
		vTaskDelay( 20 / portTICK_RATE_MS );  	
	}
}

运行结果:

计数信号量模拟停车场管理测试
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:成功申请到停车位。
KEY1被单击:不好意思,现在停车场已满!
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:释放1个停车位。
KEY2被单击:但已无车位可以释放!

互斥量–同步数据读写

static SemaphoreHandle_t  xSemaphore = NULL;
xSemaphore = xSemaphoreCreateMutex();
//发送信号量
xSemaphoreGive( xSemaphore );
//接收信号量
xSemaphoreTake( xSemaphore, portMAX_DELAY );

事件标志组–按键组合

static EventGroupHandle_t xCreatedEventGroup = NULL;
xCreatedEventGroup = xEventGroupCreate();  //创建互斥信号量

//KEY1按下置位松开清零
xEventGroupSetBits(xCreatedEventGroup, 0x01);   //bit0置位
xEventGroupClearBits(xCreatedEventGroup, 0x01); //bit0清零

//KEY2按下置位松开清零
xEventGroupSetBits(xCreatedEventGroup, 0x02);   //bit1置位
xEventGroupClearBits(xCreatedEventGroup, 0x02); //bit1清零

xEventGroupWaitBits(xCreatedEventGroup,                              //事件标志组对象
				    0x03,                                            //等待bit0和bit1
					pdTRUE,                                          //事件发生后两位清零
					pdTRUE,                                          //等待两位均置位
					portMAX_DELAY); 	                             //无期限等待
//上面函数执行后,点亮LED3

运行现象:KEY1红灯,KEY2绿灯,KEY3蓝灯,按下KEY1或者KEY2红灯或者绿灯亮,同时按下后红灯、绿灯、蓝灯均亮起,松开后只剩下蓝灯。

软件定时器

/********************************** 内核对象句柄 *******************************/
static TimerHandle_t xTimers[3] = {NULL};

static void vTimerCallback( xTimerHandle pxTimer )
{
	uint32_t ulTimerID;	
	ulTimerID = (uint32_t) pvTimerGetTimerID( pxTimer );                   //获取软件定时器的ID
	switch ( ulTimerID )
	{
		case 0:
			macLED1_TOGGLE ();                                             //切换LED1的亮灭状态
			break;
		case 1:
			macLED2_TOGGLE ();                                             //切换LED1的亮灭状态
			break;
		case 2:
			macLED3_TOGGLE ();                                             //切换LED1的亮灭状态
			break;	
    default:
        break;			
	}	
}

static void vTaskTmr( void * pvParameters )                                //Led3任务
{
	uint8_t i;
	for( i=0; i<3; i++ )
	{
	/* 创建软件定时器 */
	xTimers[i] = xTimerCreate("Timer",                                      //命名定时器
                                (i+1)*1000/portTICK_RATE_MS,                //定时的滴答数
                                pdTRUE,                                     //周期性
                                (void * const)i,                            //定时器ID
                                vTimerCallback);                            //回调函数
	}
	for( i=0; i<3; i++ )
	{
        /* 启动软件定时器 */								 
        xTimerStart(xTimers[i],                                             //软件定时器的句柄
                    portMAX_DELAY);									        //如果无法立即启动的堵塞滴答数
	}  	
	vTaskDelete( NULL );                                                    //删除定时器任务自身	
}

多内核对象测试

使用内核对象集合进行统一处理,具体实现方式在创建队列、互斥等对象后,将对象放入集合并在一个任务中统一处理:

/********************************** 内核对象句柄 *******************************/
static SemaphoreHandle_t xSemaphore = NULL;
static xQueueHandle      xQueue1    = NULL;
static xQueueHandle      xQueue2    = NULL;
static xQueueSetHandle   xQueueSet  = NULL;
/********************************** 任务函数定义 *******************************/
static void vTaskStart( void * pvParameters )                       //起始任务
{
    ......
	/* 创建二值信号量 */
	xSemaphore = xSemaphoreCreateBinary();                                    //按键信号量

	/* 创建两个消息队列 */
	xQueue1 = xQueueCreate( 10, sizeof(uint32_t) );	                          //消息队列1
	xQueue2 = xQueueCreate( 10, sizeof(uint32_t) );                           //消息队列2

	/* 创建一个内核对象集合 */
	xQueueSet = xQueueCreateSet( 1 );                                       

	
	/* 添加内核对象到对象集合 xQueueSet */
    xQueueAddToSet(xSemaphore, xQueueSet);
	xQueueAddToSet(xQueue1,    xQueueSet);
	xQueueAddToSet(xQueue2,    xQueueSet);

    ......	
}

static void vTaskPend(void *pvParameters)
{
	QueueSetMemberHandle_t xActivatedMember;
	uint32_t ulQueueMsgValue;
	uint8_t  ucQueueMsgValue;

	while(1)
	{
	    /* 等待多个内核对象 */
		xActivatedMember = xQueueSelectFromSet(xQueueSet, portMAX_DELAY);

		/* 判断接收哪个内核对象 */
		if(xActivatedMember == xQueue1)                                    //如果接收到的对象是xQueue1
		{
		    /* 接收xQueue1的消息 */
			xQueueReceive(xActivatedMember, &ulQueueMsgValue, 0);
			printf("接收到消息队列1接收到消息内容为 %d\r\n", ulQueueMsgValue);
		}
		else if(xActivatedMember == xQueue2)                               //如果接收到的对象是xQueue2
		{
		    /* 接收xQueue2的消息 */
			xQueueReceive(xActivatedMember, &ucQueueMsgValue, 0);
			printf("接收到消息队列2接收到消息内容为 %d\r\n", ucQueueMsgValue);  
		}
		else if(xActivatedMember == xSemaphore)                             //如果接收到的对象是xSemaphore
		{
			/* 接收信号量 */	
			if( xSemaphoreTake(xActivatedMember, 0) == pdPASS )
			macLED1_TOGGLE();                                               //反转LED1的亮灭状态              
		}
	}
}

任务间通信–IPC


/************************************ 任务句柄 *********************************/
static TaskHandle_t xHandleTaskWait = NULL;

static void vTaskWait( void * pvParameters )     //定义接收任务消息任务
{
	BaseType_t xResult;
	uint32_t   ulNotifiedValue;
	while(1)                                                  
	{
		xResult = xTaskNotifyWait(0x00000000,         //函数执行前保留任务消息数据的所有位
                                    0xFFFFFFFF,       //函数执行后清除任务消息数据的所有位
                                    &ulNotifiedValue, //接收任务消息数据
                                    portMAX_DELAY);   //等到有任务消息到来为止	
		if(xResult == pdPASS)
		{
			printf("接收到的任务消息数据为: %d\r\n", ulNotifiedValue);
		}
		else
		{
			macLED1_TOGGLE();                         //反转LED1的亮灭状态
		}		
	}
}

static void vTaskPost( void * pvParameters )     //定义发送任务消息任务
{
	uint32_t ucCount = 0;
	while(1)
	{
		 /* 发送任务消息 */
		xTaskNotify(xHandleTaskWait,                 //目标任务的任务句柄
					ucCount++,                       //任务消息数据
      		        eSetValueWithOverwrite);         //如果目标任务没有及时接收,上次的数据会被覆盖
		vTaskDelay( 2000 / portTICK_RATE_MS );       //每2s发送一次任务消息
	}
}

运行现象:

任务消息测试
接收到的任务消息数据为: 0
接收到的任务消息数据为: 1
接收到的任务消息数据为: 2
接收到的任务消息数据为: 3
接收到的任务消息数据为: 4
接收到的任务消息数据为: 5
接收到的任务消息数据为: 6
......

任务间通信–中断

通过按键中断获取信息,主要将发送放入中断处理函数当中:

/**
  * @brief  EXTI 中断服务函数
  * @param  无
  * @retval 无
  */
void macEXTI_INT_FUNCTION (void)
{
	static portBASE_TYPE xHigherPriorityTaskWoken;
	static uint32_t ucCount = 0;

	if(EXTI_GetITStatus(macEXTI_LINE) != RESET)           //确保是否产生了EXTI Line中断
	{
		/* 发送任务消息 */
		xTaskNotifyFromISR(xHandleTaskWait,               //目标任务的任务句柄
							ucCount++,                    //任务消息数据
							eSetValueWithoutOverwrite,    //如果目标任务没有及时接收,上次的数据会被覆盖	
							&xHigherPriorityTaskWoken);   //返回目标任务的优先级是否高于当前运行任务	

		EXTI_ClearITPendingBit(macEXTI_LINE);             //清除中断标志位	
	}
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );       //切换到更高优先级的任务
}

内存管理

/********************************** 任务函数定义 *******************************/
static void vTaskStart( void * pvParameters )                       //定义起始任务函数
{
	char * pMallocMem;
	/* 初始化 */
	LED_Init ();	        //初始化 LED
	Key_Initial ();         //初始化按键
	USARTx_Config ();       //初始化 USART1
	printf ( "\r\n内存管理测试\r\n" );

	/* 测试动态申请和释放内存块 */
	pMallocMem = (char *)pvPortMalloc(50);                             //申请动态内存块
	printf( "%s\r\n", ( char * ) pvParameters );                       //打印任务函数参数	
	strcpy( pMallocMem, pvParameters );                                //拷贝任务函数参数到动态内存块
	printf( "%s\r\n", pMallocMem );                                    //打印动态内存块里的字符串
	vPortFree(pMallocMem);                                             //如果动态内存块不再使用,应该释放它
	
	vTaskDelete( NULL );                                               //删除起始任务自身
	
	
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32 Free RTOS实战 的相关文章

  • [屏驱相关]【SWM166-SPI-Y1.28C1测评】+ 有点惊艳的开箱

    耳闻华芯微特许久了 看到论坛得评测活动赶紧上了末班车 毕竟对有屏幕得板子也是很喜欢得 京东快递小哥客客气气 微笑着把快递给了我 好评 直接拆了包 在此之前没看过视频号 所以这个圆盘盘得模具还是有点惊喜的 正面照如下 开机有灯光秀 还有动画
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 释放内存时堆损坏

    我有一堂课如下 struct CliHandler CliHandler int argc char argv CliHandler int doWork int argc char argv private CliHandler cons
  • “免费”的冲突类型

    我收到错误 免费 的冲突类型 打电话给free 下面的函数 int main char fx x 2 5 x 1 node fxNode buildTree fx sizeof fx sizeof char printf deriveFro
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • RT-Thread 内核基础(五)

    使用static修饰全局变量作用 限制作用域 如果全局变量前面加上 static 关键字 那么该变量的作用域将被限制在声明它的源文件中 即它将成为一个文件作用域的静态变量 其它源文件无法访问这个变量 这对于控制变量的可见性和避免命名冲突是有
  • 当尝试释放堆管理器分配的内存时会发生什么,而堆管理器分配的内存超出了要求的内存?

    这个问题是在一次采访中问我的 假设 char p malloc n 分配了 n 个以上的内存 即分配了 N 个字节的内存 并且使用 free p 来释放分配给 p 的内存 堆管理器可以执行这种错误的分配吗 现在会发生什么 是释放 n 个字节
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • 核心耦合内存在 STM32F4xx 上可执行吗?

    尝试从 STM32F429s CCM 运行代码 但每当我命中 CCM 中的第一条指令时 我总是会遇到硬故障 并且 IBUSERR 标志被设置 该指令有效且一致 STM32F4xx 是否可能不允许从 CCM 执行 数据访问效果良好 alios
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • 如何在其自身事件中释放控件?

    我有一个清单TPanels在 FMX 应用程序中 如果我单击面板 我想释放它 直接在 Onclick 处理程序中释放它们不是正确的方法 因为我遇到了访问冲突 我不想使用windowsmessages 推荐于如何释放其事件处理程序内部的控制权
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 如何释放字符指针数组?

    我使用此方法将列表中的值转换为数组 以便在 execvp 系统调用中使用 char list2argarray struct shellvalue values int count char array char malloc count

随机推荐

  • 在Vf中如何将Excel数据导入(用Vf来导)?

    请大侠们赐教 使用import命令 xff0c 如 xff1a IMPORT FROM 表1 xls TYPE xls 将表1 xls导入为表1 dbf 点击 文件 xff0d gt 导入 xff0d gt 类型选择 xff1a Micro
  • 3.3 生产管理系统需求分析

    根据以上对生产管理内容和生产管理系统的分析 xff0c 一个标准的MRP生产管理系统应该包括如图3 12所示的几大功能 除此之外系统还应包括信息系统必须具备的通用功能 xff0c 例如系统管理 权限设置 数据备份与恢复等 xff0c 这些功
  • Spring源码之事物注解@Transactional原理(源码层面)

    官方文档地址 xff1a https docs spring io spring docs 4 3 21 RELEASE spring framework reference htmlsingle transaction 我翻译的地址 xf
  • 設計公司軟件開發需求分析流程

    工作流程 一 平面设计客户合作流程 信息收集 1 客户提出工作要求 2 客户提供相美文本及图片资料 公司介绍 项目描述 基本设计要求 提案 1 双方就设计内容进行协商 xff0c 修改 补充 xff0c 以达成共识 2双方确定设计具体细节及
  • DBcontext应用于已存在数据库

    EF4 1有三种方式来进行数据操作及持久化 分别是Database First Model First Code first xff0c 前面都已经简单介绍过了 下面简单小结一下 xff1a 1 Database First 是基于已存在的
  • 没有为该对象定义无参数的构造函数(MVC 之DefaultControllerFactory 依赖注入)

    Asp net mvc2中提供很多可以扩展的地方 xff0c 利用这些扩展之后 xff0c asp net mvc使用起来更加灵活 Simone Chiaretta曾写过一篇文章 xff1a 13 ASP NET MVC extensibi
  • Entity Framework 学习总结之一:ADO.NET 实体框架概述

    ADO NET 实体框架概述 新版本中的 ADO NET 以新实体框架为特色 它使开发人员可以通过对象模型 xff08 而不是逻辑 关系数据模型 xff09 专注于数据 实体框架有助于将逻辑数据架构抽象为概念模型 xff0c 并且允许以多种
  • Entity Framework 学习总结之四:对象服务介绍使用

    System Data Objects System Data Entity dll 该命名空间包含一些类 xff0c 用于提供对 对象服务 的核心功能的访问 这些类使您可以藉由作为实体类型实例的强类型 CLR 对象来查询 插入 更新和删除
  • Entity Framework 学习总结之四:对象服务介绍使用

    System Data Objects System Data Entity dll 该命名空间包含一些类 xff0c 用于提供对对象服务的核心功能的访问 这些类使您可以藉由作为实体类型实例的强类型 CLR 对象来查询 插入 更新和删除数据
  • 未执行的URL(MVC异常)

    昨天开始就碰到在IIS里面通过URL无法直接访问到图片 xff0c 提示错误 xff0c 所以经过研究发现 xff0c 合理的配置节应该如下 先改成集成模式 xff0c 然后再改成经典模式 lt system webServer gt lt
  • PIX学习路径-1-选择PIXHAWK作为飞控学习的起点

    xff08 先声明出处 xff1a http blog csdn net qq 21842557 article details 52214425 xff09 创业领域现在最火爆的是什么 xff1f 无疑是机器人和无人机 越来越多的巨头和V
  • PIX学习路径-3-PIXHAWK二次开发之前需要知道的事

    现在作为一个consumer xff0c 能够实现将飞机装配 xff0c 使用MP进行固件烧录 xff0c 初始化校准 xff0c 然后还能够调节PID xff0c 这样算是一个合格的consumer了 xff0c 现在希望对PIXHAWK
  • Java面试题全集(上)

    2013年年底的时候 xff0c 我看到了网上流传的一个叫做 Java面试题大全 的东西 xff0c 认真的阅读了以后发现里面的很多题目是重复且没有价值的题目 xff0c 还有不少的参考答案也是错误的 xff0c 于是我花了半个月时间对这个
  • Netty学习:Channel及其内部接口Unsafe

    连接到网络套接字或组件的一种连接 xff0c 它能够进行I O操作 xff0c 如读 写 连接和绑定 通道为用户提供 通道的当前状态 例如是否打开 它是连接吗 通道的 64 linkplain ChannelConfig配置参数 如接收缓冲
  • 拥抱开源

    使用linux ubuntu 已经一个月多了 xff0c 偶尔用windows是因为要改vb delphi net的程序 在linux下 xff0c 似乎多数软件都是开源的 xff0c 免费的 如今我算是终于义无反顾的走上了这条路了 jav
  • STM32 | C语言对寄存器的封装

    说明 xff1a 这里以GPIO外设为例 xff0c 介绍C语言对寄存器的封装 以此类推其他外设同样可以用这种方法来封装 本文有两部分构成 xff1a 1 介绍宏定义 2 使用结构体封装寄存器列表 1 宏定义 以封装STM32 GPIOH为
  • Intel CPU(i3、i5、i7、i9)型号、性能详细解读

    一 Intel CPU的性能比较 xff1a 它们分为高中低端 xff0c 最低端的G系列 xff0c 然后是低端i3系列 xff0c 中端i5系列 xff0c 高端i7系列和至尊i9系列 Intel CPU 末尾字母含义 xff08 M
  • 字符串搜索函数

    一 字符串中找字符 char strchr const char s int c 表示从左边 开始找这个字符第一次出现的位置 char strrchar const char s int c 表示 从右边 开始找这个字符第一次出现的位置 注
  • 4. Service

    4 Service k8s 中的Pod是朝生夕死的 xff0c 并且是不会重生的 xff0c 尤其是在ReplicaSets中动态创建或销毁Pod 然而每个Pod可以获取自己的IP地址 xff0c 即使这些IP地址是不稳定的 xff08 重
  • STM32 Free RTOS实战

    FreeRTOS是一个开源的实时操作系统 使用的平台 xff1a 秉火STM32 Cortex M3内核开发板 xff0c Free RTOS v8 2 3 多任务流水灯 span class token builtin class nam