智能教室控制系统

article/2025/10/25 22:12:43

智能教室控制系统

引言

概述

该系统通过上位机C#控制下位机STM32,实现教室打卡考勤功能,通过打卡对数据库SQLserver进行增删改查,同时能将数据库的数据导出表格,下位机用到RFID的RC522模块,舵机、风扇,ws2812灯环。风扇通过调温度阈值,自动开关。上位机和下位机通过串口进行通信。运用技术:C#桌面级winform程序、SQL server、stm32f103zet6单片机技术路线:软件部分:C#:三方API接入 json解析、串口通信、调用数据库硬件部分:Rfid射频刷卡,舵机,风扇

舵机模块
在这里插入图片描述橙色线接脉冲线,红色线接+5V,黑色接GND;

RC522模块
在这里插入图片描述
上位机共有5个界面,分别是注册,登录,忘记密码,主界面,导出表单。
在这里插入图片描述

登录界面

在这里插入图片描述

忘记密码界面

在这里插入图片描述

注册界面

在这里插入图片描述

导出表单

代码部分

下位机代码

主函数

#include "bsp.h"				/* 底层硬件驱动 */#include "pwm.h"/*
STM32 每个系列都会有唯一的一个芯片序列号(96 位 bit):
STM32F10X 的地址是 0x1FFFF7E8 
STM32F20X 的地址是 0x1FFF7A10
STM32F30X 的地址是 0x1FFFF7AC
STM32F40X 的地址是 0x1FFF7A10
STM32L1XX 的地址是 0x1FF80050
*//* SN 起始地址 */
#define STM32F10X_SN_ADDR 0x1FFFF7E8/* 定义例程名和例程发布日期 */
#define EXAMPLE_NAME "WSNEP_V01-051_SPI 实验( RC522) "
#define EXAMPLE_DATE "2021-06-01"
#define DEMO_VER "1.0"/* 定义 LCD 显示相关公共信息 */
#define DEV_NAME "Wisdomclassroom"
#define LCD_EXAMPLE_NAME "RFID"const unsigned char str1[] = {0x08,0x00,0x29,0x00,0xCA,0x00,0x4C,0xFF,0x78,0x92,0x4C,0x92,0x4A,0x92,0x08,0x92,0x00,0x92,0x7E,0x92,0x42,0x92,0x42,0xFF,0x42,0x00,0x7E,0x00,0x00,0x00,0x00,0x00};/*"智",0*/
const unsigned char str2[] = {0x44,0x01,0x54,0x06,0x55,0x10,0xFF,0x50,0x55,0x56,0x55,0x51,0x45,0x51,0x01,0x59,0x45,0x55,0x55,0x51,0x55,0x51,0xFF,0x53,0x55,0xF0,0x54,0x04,0x44,0x03,0x00,0x00};/*"慧",1*/
const unsigned char str3[] = {0x04,0x20,0x25,0x50,0x25,0x92,0x25,0x11,0xFF,0x7E,0x25,0xA0,0x2D,0x20,0x14,0x21,0x21,0x02,0x0E,0x04,0xF1,0xC8,0x10,0x30,0x10,0xCC,0x1F,0x02,0x10,0x01,0x00,0x00};/*"教",2*/
const unsigned char str4[] = {0x08,0x02,0x30,0x02,0x24,0x12,0x24,0x92,0x25,0x92,0x26,0x92,0xA4,0x92,0x64,0xFE,0x24,0x92,0x24,0x92,0x25,0x92,0x24,0xD2,0x24,0x12,0x28,0x02,0x30,0x02,0x00,0x00};/*"室",3*/
const unsigned char str5[] = {0x02,0x00,0x42,0x00,0x33,0xFE,0x00,0x04,0x00,0x08,0x22,0x00,0x2A,0xFF,0x2A,0xA8,0x2A,0xA8,0xFE,0xA8,0x2A,0xAA,0x2A,0xA9,0x2A,0xFE,0x22,0x00,0x02,0x00,0x00,0x00};/*"请",4*/
const unsigned char str6[] = {0x00,0x08,0x00,0x70,0x7F,0x80,0x48,0xFC,0x48,0x80,0x48,0x80,0x4F,0xFF,0x48,0x88,0x48,0x84,0x78,0xF8,0x00,0x00,0x0F,0xF0,0x00,0x02,0x00,0x01,0xFF,0xFE,0x00,0x00};/*"刷",5*/
const unsigned char str7[] = {0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0xFF,0xFF,0x22,0x00,0x22,0x00,0x22,0x40,0x22,0x20,0x22,0x10,0x22,0x08,0x02,0x00,0x02,0x00,0x00,0x00};/*"卡",6*/void IC_test( void )
{char cStr [ 30 ];char EptStr[30];uint8_t ucArray_ID [ 4 ]; /*先后存放 IC 卡的类型和 UID(IC 卡序列号)*/uint8_t ucStatusReturn; /*返回状态 */static u16 ucLineCount = 170; /* LCD 起始行为 170 */sprintf ( EptStr, "                "); /* LCD 显示空白,为清空 LCD 显示做准备 *//*寻卡*/if ( ( ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID ) ) != MI_OK ){/*若失败再次寻卡*/ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID );}if ( ucStatusReturn == MI_OK ){//		printf("----------------------------\r\n");//		printf("0x%02X%02X\r\n",ucArray_ID [ 0 ],ucArray_ID [ 1 ]);/*防冲撞(当有多张卡进入读写器操作范围时,防冲突机制会从其中选择一张进行操作) */if ( PcdAnticoll ( ucArray_ID ) == MI_OK ){sprintf ( cStr, "%02X%02X%02X%02X",ucArray_ID [ 0 ],ucArray_ID [ 1 ],ucArray_ID [ 2 ],ucArray_ID [ 3 ]);//printf("%s",ucArray_ID);		//			USART1_Send_Data((uint8_t*)ucArray_ID,4);printf ( "%s",cStr );if ( ucLineCount == 290 ) /* 最多同时显示 6 行 */{for(ucLineCount=170;ucLineCount<=290;ucLineCount+=20){LCD_ShowString(30,ucLineCount,200,16,16,(u8*)EptStr); //循环清空 6 行 LCD 显示}ucLineCount=170; /* 设置 LCD 起始行为 170 */}			LCD_ShowString(30,ucLineCount,200,16,16,(u8*)cStr); //显示读取到的卡号ucLineCount += 20; /* 设置下一次 LCD 显示行,自增 20 */}}
}/*
*********************************************************************************************************
*	函 数 名: main
*	功能说明: c程序入口
*	形    参:无
*	返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{		uint8_t lcd_id[12]; /* 存放 LCD ID 字符串 */
//	uint8_t a0;/*ST 固件库中的启动文件已经执行了 SystemInit() 函数,该函数在 system_stm32f10x.c 文件,主要功能是配置 CPU 系统的时钟,内部 Flash 访问时序,配置 FSMC 用于外部 SRAM*/bsp_Init(); /* 硬件初始化 */TIM_Init();
//	SMBus_Init();//人体红外初始化
//	bsp_InitUART5(9600);/*注意,串口 4 初始化放在 LCD 之前*/TFTLCD_Init(); /* TFTLCD 初始化*/bsp_InitWS2812B(); /* 初始化 WS2812B */POINT_COLOR=BLUE;sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将 LCD ID 打印到 lcd_id 数组。LCD_ShowString(30,40,200,24,24,(uint8_t*)DEV_NAME);LCD_ShowString(30,70,200,16,16,(uint8_t*)LCD_EXAMPLE_NAME);LCD_ShowString(30,90,200,16,16,(uint8_t*)DEMO_VER);LCD_ShowString(30,110,200,16,16,lcd_id); //显示 LCD IDLCD_ShowString(30,130,200,12,12,(uint8_t*)EXAMPLE_DATE);//汉字部分Show_Graph(30,150,(u8*)str1,16,0);Show_Graph(45,150,(u8*)str2,16,0);Show_Graph(60,150,(u8*)str3,16,0);Show_Graph(75,150,(u8*)str4,16,0);Show_Graph(105,150,(u8*)str5,16,0);Show_Graph(120,150,(u8*)str6,16,0);Show_Graph(135,150,(u8*)str7,16,0);bsp_InitRc522(); /* 初始化 RC522 的 SPI 端口 */PcdReset(); /* 复位 RC522 */M500PcdConfigISOType('A'); /* 设置工作方式 */bsp_StartAutoTimer(0, 300); /* 定时器 0 周期 300 毫秒 */bsp_StartAutoTimer(1, 500); /* 定时器 1 周期 500 毫秒 */while(1){		bsp_Idle(); /* CPU 空闲时执行的函数,在 bsp.c */if (bsp_CheckTimer(0)) /* 定时到 */{bsp_LedToggle(2);		}if (bsp_CheckTimer(1)) /* 定时到 */{IC_test();}}
}

串口通信模块

#include "bsp.h"
#include "bsp_fan.h"
#include "bsp_uart5.h"static const uint8_t temp[16] = {0XFD,0X00,0X0D,0X01,0X01,0XBB,0XD4,0XB8,0XE7,0XB4,0XF8,0XB4,0XF8,0XCE,0XD2,0XDC};
static const uint8_t temp1[16] = {0XFD,0X00,0X0D,0X01,0X01,0XC0,0XA4,0XB8,0XE7,0XB4,0XF8,0XB4,0XF8,0XCE,0XD2,0XD7};#if EN_USART1_RXuint8_t USART_RX_BUF[USART_REC_LEN];		//接收缓冲,最大USART_REC_LEN个字节,末字节为换行符
uint8_t ReceiveState=0;									//接收状态标记
uint16_t RxCounter=0;u16 USART_RX_STA=0;       //接收状态标记#endif /*
*********************************************************************************************************
*	函 数 名:bsp_InitUart
*	功能说明:初始化 CPU 的 USART1 串口硬件设备
*	形    参:无
*	返 回 值:无
*********************************************************************************************************
*//*
********************************************************************************************************
*/
//加入以下代码,支持 printf 函数,而不需要选择 use MicroLIB 
#if 1
#pragma import(__use_no_semihosting) 
/* 标准库需要的支持函数 */ 
struct __FILE 
{ 
int handle; 
}; 
FILE __stdout; 
/* 定义_sys_exit()以避免使用半主机模式 */ void _sys_exit(int x) 
{ 
x = x; 
} 
/*
*********************************************************************************************************
* 函 数 名: fputc
* 功能说明: 重定义 putc 函数,这样可以使用 printf 函数从串口 1 打印输出
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
int fputc(int ch, FILE *f)
{ 
while((USART1->SR&0X40)==0){};//;//循环发送,直到发送完毕 USART1->DR = (u8) ch; 
return ch;
}
#endifvoid bsp_InitUart1(uint32_t baud)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;#if EN_USART1_RX	//如果使能了接收NVIC_InitTypeDef NVIC_InitStructure;#endif/* 串口 1 TX = PA9 RX = PA10 *//* 第 1 步: 配置 GPIO *//* 打开 GPIO 时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/* 打开 UART 时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);/* 配置 USART Tx 为复用功能 */ //USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;		//PA.9GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	//复用推挽输出	GPIO_Init(GPIOA,&GPIO_InitStructure);		//初始化 GPIOA.9/* 配置 USART Rx 为复用功能 */ //USART1_RX GPIOA.10 初始化GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;		//PA.10GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;	//浮空输入	GPIO_Init(GPIOA,&GPIO_InitStructure);		//初始化 GPIOA.10/* 第 2 步: 配置串口硬件参数 */USART_InitStructure.USART_BaudRate=baud;		//波特率USART_InitStructure.USART_WordLength=USART_WordLength_8b;		//字长为8位数据格式USART_InitStructure.USART_StopBits=USART_StopBits_1;		//一个停止位USART_InitStructure.USART_Parity=USART_Parity_No;		//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;	//无硬件数据流控制USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;		//收发模式USART_Init(USART1,&USART_InitStructure);	//初始化串口#if EN_USART1_RX		//如果使能了接收/* 第 3 步: Usart1 NVIC 配置 */NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;		//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;		//IRQ 通道使能NVIC_Init(&NVIC_InitStructure);		//根据指定的参数初始化 VIC 寄存器USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);		/* 开启串口接受中断 */USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);		 /* 开启串口空闲中断 */#endif	/* 第 4 步: 使能串口 1 */USART_Cmd(USART1,ENABLE);  //使能串口	
}/*
*********************************************************************************************************
*	函 数 名:USART1_IRQHandler
*	功能说明:USART1 中断,主要是接收中断和空闲中断
*	形    参:无
*	返 回 值:无
*********************************************************************************************************
*/
void USART1_IRQHandler(void)		//串口 1 中断服务程序
{u8 Res;	bsp_InitUART5(9600);/*注意,串口 4 初始化放在 LCD 之前*/	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);Res=USART_ReceiveData(USART1);	//读取接收到的数据bsp_InitFan(); /* 初始化风扇 */if(Res=='1' || Res==0x01)		//接收到1或0x01,正转舵机3s,停止{TIM_SetCompare1(TIM1,10);delay_ms(3000);TIM_SetCompare1(TIM1,15);}if(Res=='2' || Res==0x02)		//接收到2或0x02,反转转舵机3s,停止{TIM_SetCompare1(TIM1,20);delay_ms(3000);TIM_SetCompare1(TIM1,15);}if(Res=='3'||Res==0x03) 		//开灯环{WS2812_effect(1);}if(Res=='4'||Res==0x04)			//关灯环{WS2812_effect(0);}if(Res=='5'||Res==0x05){bsp_FanOn(1);bsp_FanOn(2);}if(Res=='6'||Res==0x06){bsp_FanOff(1);bsp_FanOff(2);}	if(Res=='7'||Res==0x07){bsp_BeepToggle();delay_ms(200);bsp_BeepToggle();}if(Res=='8'||Res==0x08){bsp_BeepOff;}USART_ClearITPendingBit(USART1,USART_IT_RXNE);		USART_RX_STA=0;		}	/*
*********************************************************************************************************
* 函 数 名: USART1_Send_Data
* 功能说明: USART1 发送 len 个字。
* 形 参: buf:发送区首地址
* len:发送的字节数 0~255
* 返 回 值: 无
*********************************************************************************************************
*/
void USART1_Send_Data(uint8_t *buf,uint8_t len)
{uint8_t t;for(t=0;t<len;t++) //循环发送数据{while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);USART_SendData(USART1,buf[t]);}while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

uart.h


#ifndef _BSP_UART_H_
#define _BSP_UART_H_#include "sys.h"#define USART_REC_LEN				1024		//定义最大接收字节数1024
#define EN_USART1_RX				1				//使能(1)/禁止(0)串口1接收extern uint8_t USART_RX_BUF[USART_REC_LEN];		//接收缓冲,最大USART_REC_LEN个字节,末字节为换行符
extern uint8_t ReceiveState;									//接收状态标记
extern uint16_t RxCounter;void bsp_InitUart1(uint32_t baud);#if EN_USART1_RX		//如果使能了接收void Uart0_STA_Clr(void);void USART1_Send_Data(uint8_t *buf,uint8_t len);#endif#endif/***************************** 德致伦电子 DeZLinc (END OF FILE) *********************************/

PWM模块部分

#include "pwm.h"/*
*********************************************************************************************************
* 函 数 名: bsp_GetRCCofGPIO
* 功能说明: 根据 GPIO 得到 RCC 寄存器
* 形 参:无
* 返 回 值: GPIO 外设时钟名
*********************************************************************************************************
*/static void TIM_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 输出比较通道 GPIO 初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// BKIN引脚默认先输出低电平GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}static void Advance_TIM_Config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef  TIM_OCInitStructure;// 开启定时器时钟,即内部时钟CK_INT=72MRCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);/*--------------------时基结构体初始化-------------------------*///TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period= (200-1);	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= (7200-1);	// 时钟分频因子 ,用于配置死区时间,没用到,随意TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		// 计数器计数模式,设置为向上计数TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		// 重复计数器的值,没用到,可以随意设置TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	// 初始化定时器TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);/*--------------------输出比较结构体初始化-------------------*/		// 配置为PWM模式2TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 互补输出使能TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 设置占空比大小TIM_OCInitStructure.TIM_Pulse = 0;// 输出通道电平极性配置TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道空闲电平极性配置TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;TIM_OC1Init(TIM1, &TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);// 使能计数器TIM_Cmd(TIM1, ENABLE);	// 主输出使能,当使用的是通用定时器时,这句不需要TIM_CtrlPWMOutputs(TIM1, ENABLE);
}void TIM_Init(void)
{TIM_GPIO_Config();Advance_TIM_Config();
}

ws2812.c

#include "bsp.h"static void send_Data_rgb(uint8_t r,uint8_t g, uint8_t b);uint16_t LED_BYTE_Buffer[LED_BYTE_Buffer_Size]; //发送数组缓存/*
*********************************************************************************************************
* 函 数 名: bsp_InitWS2812B
* 功能说明: 配置 WS2812 灯相关的 GPIO 和 TIM PWM 功能
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/extern const uint8_t test_color[9][3] = {{0, 0, 0 },//黑色(不亮){32, 32, 32},//白色{64, 0, 0 },//红色{0, 64, 0 },//绿色{0, 0, 64},//蓝色{64, 64, 0 },//黄色{64, 32, 0 },//橙色{64, 0, 64},//紫红色{0, 64, 64},//青色
};void bsp_InitWS2812B(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;GPIO_InitTypeDef GPIO_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_APB2PeriphClockCmd(WS2812_GPIO_RCC, ENABLE); //使能 GPIO 时钟GPIO_InitStructure.GPIO_Pin = WS2812_GPIO_Pin;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(WS2812_GPIO_Port, &GPIO_InitStructure);RCC_APB1PeriphClockCmd(WS2812_TIM_RCC, ENABLE); //使能定时器 x 时钟/* Time base configuration */TIM_TimeBaseStructure.TIM_Period = 89; // 800kHz = 72M/(89+1)/(0+1)=800KHzTIM_TimeBaseStructure.TIM_Prescaler = 0;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式TIM_TimeBaseInit(WS2812_TIM, &TIM_TimeBaseStructure); //根据 TIM_TimeBaseInitStruct 中指定的参数初始化TIMx 的时间基数单位/* PWM1 Mode configuration: Channelx */TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM 脉冲宽度调制模式 1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_Pulse = 0;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM 输出比较极性高WS2812_TIM_OCxInit(WS2812_TIM, &TIM_OCInitStructure); //配置输出设置函数/* 配置 DMA *//* 使能 DMA 时钟 */RCC_AHBPeriphClockCmd(WS2812_DMA_RCC, ENABLE);/* 配置 WS2812 所用 TIM 的 DMA 通道信息 */DMA_DeInit(WS2812_DMA_CH);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&WS2812_DMA_ADDR; //DMA 外设基地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer; //DMA 内存基地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设DMA_InitStructure.DMA_BufferSize = LED_BYTE_Buffer_Size; //DMA 通道的 DMA 缓存的大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为 16 位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为 16 位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在正常模式 // stop DMA feed after buffer size is reachedDMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA 通道 x 拥有高优先级DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA 通道 x 没有设置为内存到内存传输DMA_Init(WS2812_DMA_CH, &DMA_InitStructure); //根据 DMA_InitStruct 中指定的参数初始化 DMA 的通道/* 只能使用通道 x TIMx_UP */TIM_DMACmd(WS2812_TIM, TIM_DMA_Update, ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名: send_Data_rgb
* 功能说明: 发送一次数据
* 形 参: red 红色数值, green 绿色数值, blue 蓝色数值
* 返 回 值: 无
*********************************************************************************************************
*/
static void send_Data_rgb(uint8_t red,uint8_t green, uint8_t blue)
{uint8_t i=0;//注意需要发送的数据顺序高位->低位的顺序 是 绿->红->蓝uint32_t rgb_value = ( ( (uint32_t)green ) << 16 ) | ( ( (uint32_t)red ) << 8 ) | ( (uint32_t)blue );for(i=0;i<24;i++){//判断最高位是否为 1,而赋值LED_BYTE_Buffer[i] = ( ( rgb_value << i ) & 0x800000 ) > 0 ? TIMING_ONE : TIMING_ZERO;}DMA_SetCurrDataCounter(WS2812_DMA_CH, LED_BYTE_Buffer_Size); // 装载需要发送的数据长度到 DMA 通道DMA_Cmd(WS2812_DMA_CH, ENABLE); // 使能对应的 DMA 通道TIM_Cmd(WS2812_TIM, ENABLE); // 使能对应的 TIMxwhile(!DMA_GetFlagStatus(WS2812_DMA_TC)); // 等待传输完毕TIM_Cmd(WS2812_TIM, DISABLE); // 失能对应的 TIMxDMA_Cmd(WS2812_DMA_CH, DISABLE); // 失能对应的 DMA 通道DMA_ClearFlag(WS2812_DMA_TC); // 清除对应的 DMA 传输完成标志位}/*
*********************************************************************************************************
* 函 数 名: ws2812Send
* 功能说明: 发送一次灯带数据
* 形 参: uint8_t (*color)[3] 是二维数组(按照[0]对应红色数值,[1]对应绿色数值,[2]对应蓝色数值)
* uint16_t len 需要同时操作的灯的数量(注意,不要超过 NBR_LEDS)
* 返 回 值: 无
*********************************************************************************************************
*/
void ws2812Send(uint8_t (*color)[3], uint16_t len)
{uint16_t i = 0;if(len>NBR_LEDS){printf("操作的灯数量超出定义\r\n");return;}for(i = 0;i < NBR_LEDS; i++){if(i<len){send_Data_rgb(color[i][0],color[i][1],color[i][2]);  //调换rgb 灯环的颜色顺序导致不同}else{send_Data_rgb(0,0,0);//灭剩余的灯 ,注意,黑色的 rgb 为 0,0,0}}
}/*
*********************************************************************************************************
* 函 数 名: WS2812_effect
* 功能说明: WS2812 效果
* 形 参: uint8_t effect 效果参数
* 返 回 值: 无
*********************************************************************************************************
*/
void WS2812_effect(uint8_t effect)
{uint8_t i=0;uint8_t buf[NBR_LEDS][3] = {0};for(i=0;i<NBR_LEDS;i++) //填充数值{buf[i][0] = test_color[effect][0];buf[i][1] = test_color[effect][1];buf[i][2] = test_color[effect][2];}ws2812Send(buf,NBR_LEDS); //显示
}

ws2812.h

#ifndef __BSP_WS2812_H
#define __BSP_WS2812_H
#include "sys.h"
/
移植修改区
按照实际端口修改
较前版本更加容易移植(注意,端口仅仅适用于非 JTAG/SWD 引脚,如果是 JTAG 引脚,需要打开 AFIO 时钟,并失能JTAG)
//注意,配合程序仅适用于 TIM2~TIM5 通用定时器#define WS2812_GPIO_RCC RCC_APB2Periph_GPIOB //端口时钟
#define WS2812_GPIO_Pin GPIO_Pin_6 //引脚号
#define WS2812_GPIO_Port GPIOB //端口号
#define WS2812_TIM_RCC RCC_APB1Periph_TIM4 //定时器时钟#define WS2812_TIM TIM4 //定时器
#define WS2812_TIM_OCxInit TIM_OC1Init //定时器比较函数
#define WS2812_DMA_RCC RCC_AHBPeriph_DMA1 //DMA 时钟#define WS2812_DMA_ADDR TIM4->CCR1 //连接的外设基地址
#define WS2812_DMA_CH DMA1_Channel7 //DMAx 通道
#define WS2812_DMA_TC DMA1_FLAG_TC7 //DMAx 传输完成标志/
#define TIMING_ONE 61 //T1H 1 码 68%占空比 68%*89=61
#define TIMING_ZERO 28 //T0L 0 码 32%占空比 32%*89=28
#define LED_BYTE_Buffer_Size 24 //RGB 共 24
#define NBR_LEDS 12 //WS2812 RGB 灯个数/* 供外部调用的函数声明 */
void bsp_InitWS2812B(void);void ws2812Send(uint8_t (*color)[3], uint16_t len);
void WS2812_effect(uint8_t effect);
#endif

RC522.c

#include "bsp.h"
/*
*********************************************************************************************************
* 函 数 名: bsp_InitRc522
* 功能说明: 初始化 RC522 的 IO 口和 SPI 功能配置
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitRc522(void)
{SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_ALL_RC522, ENABLE ); //RC522 时钟使能GPIO_InitStructure.GPIO_Pin = RC522_CS_GPIO_PIN; // RC522_CS 推挽GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(RC522_CS_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = RC522_RST_GPIO_PIN; // RC522_RST 推挽GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(RC522_RST_GPIO_PORT, &GPIO_InitStructure);RC522_CS = 1; //RC522 不选中RC522_RST = 1; //RC522 不复位bsp_InitSPIx(RC522_SPIx); //初始化 CLK,MISO,MOSI 三个端口和 SPI 时钟/* SPI 模式配置 */// FLASH 芯片 支持 SPI 模式 0,据此设置 CPOL CPHASPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(RC522_SPIx , &SPI_InitStructure);/* 使能 SPI */SPI_Cmd(RC522_SPIx , ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名: SPI_RC522_SendByte
* 功能说明: 从 SPI 总线写入一个字节
* 形 参: byte:要写入的字节
* 返 回 值: 返回接收到的数据
*********************************************************************************************************
*/
uint8_t SPI_RC522_SendByte(uint8_t byte)
{return SPIx_ReadWriteByte(RC522_SPIx,byte);
}
/*
*********************************************************************************************************
* 函 数 名: SPI_RC522_ReadByte
* 功能说明: 从 SPI 总线读取一个字节
* 形 参: 无
* 返 回 值: 读取到的字节
*********************************************************************************************************
*/
uint8_t SPI_RC522_ReadByte(void)
{return (SPI_RC522_SendByte(RC522_Dummy_Byte));
}
/*
*********************************************************************************************************
* 函 数 名: ReadRawRC
* 功能说明: 读 RC522 寄存器
* 形 参: Address:寄存器地址
* 返 回 值: 读出的值
*********************************************************************************************************
*/
uint8_t ReadRawRC(uint8_t Address)
{uint8_t ucAddr;uint8_t ucResult=0;ucAddr = ( ( ( Address <<1 ) & 0x7E ) | 0x80 );/*选择 RC522: CS 低 *//* 通讯开始: CS 低 */RC522_CS = 0;SPI_RC522_SendByte( ucAddr );ucResult = SPI_RC522_ReadByte();/* 停止信号 RC522: CS 高 *//* 通讯开始: CS 低 */RC522_CS = 1;return ucResult;
}
/*
*********************************************************************************************************
* 函 数 名: ReadRawRC
* 功能说明: 写 RC522 寄存器
* 形 参: uint8_t Address:寄存器地址
* uint8_t value:写入的值
* 返 回 值: 无
*********************************************************************************************************
*/
void WriteRawRC(uint8_t Address, uint8_t value)
{uint8_t ucAddr;ucAddr = ( ( Address << 1 ) & 0x7E );/*选择 RC522: CS 低 *//* 通讯开始: CS 低 */RC522_CS = 0;SPI_RC522_SendByte( ucAddr );SPI_RC522_SendByte( value );/* 停止信号 RC522: CS 高 *//* 通讯开始: CS 低 */RC522_CS = 1;
}
/*
*********************************************************************************************************
* 函 数 名: SetBitMask
* 功能说明: 对 RC522 寄存器置位
* 形 参: uint8_t ucReg,寄存器地址
* uint8_t ucMask,置位值
* 返 回 值: 无
*********************************************************************************************************
*/
void SetBitMask ( uint8_t ucReg, uint8_t ucMask )
{uint8_t ucTemp = 0;ucTemp = ReadRawRC ( ucReg );WriteRawRC ( ucReg, ucTemp | ucMask ); // set bit mask
}
/*
*********************************************************************************************************
* 函 数 名: ClearBitMask
* 功能说明: 对 RC522 寄存器清位
* 形 参: uint8_t ucReg,寄存器地址
* uint8_t ucMask,清位值
* 返 回 值: 无
*********************************************************************************************************
*/
void ClearBitMask ( uint8_t ucReg, uint8_t ucMask )
{uint8_t ucTemp = 0;ucTemp = ReadRawRC ( ucReg );WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) ); // clear bit mask
}
/*
*********************************************************************************************************
* 函 数 名: PcdAntennaOn
* 功能说明: 开启天线
* 形 参: 无
* 返 回 值: 无
* 注 意:每次启动或关闭天险发射之间应至少有 1ms 的间隔
*********************************************************************************************************
*/
void PcdAntennaOn ( void )
{uint8_t uc;uc = ReadRawRC ( TxControlReg );if ( ! ( uc & 0x03 ) ){SetBitMask( TxControlReg, 0x03 );}
}
/*
*********************************************************************************************************
* 函 数 名: PcdAntennaOff
* 功能说明: 关闭天线
* 形 参: 无
* 返 回 值: 无
* 注 意:每次启动或关闭天险发射之间应至少有 1ms 的间隔
*********************************************************************************************************
*/
void PcdAntennaOff ( void )
{ClearBitMask ( TxControlReg, 0x03 );
}
/*
*********************************************************************************************************
* 函 数 名: PcdReset
* 功能说明: 复位 RC522
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void PcdReset ( void )
{/* 复位 RC522: RST 高 */RC522_RST = 1;delay_us(10); //_NOP();/* 取消复位 RC522: RST 低 */RC522_RST = 0;delay_us(10); //_NOP();/* 复位 RC522: RST 高 */RC522_RST = 1;delay_us(10); //_NOP();WriteRawRC ( CommandReg, 0x0f );while ( ReadRawRC ( CommandReg ) & 0x10 );delay_us(10); //_NOP();WriteRawRC ( ModeReg, 0x3D ); //定义发送和接收常用模式 和 Mifare 卡通讯, CRC 初始值 0x6363WriteRawRC ( TReloadRegL, 30 ); //16 位定时器低位WriteRawRC ( TReloadRegH, 0 ); //16 位定时器高位WriteRawRC ( TModeReg, 0x8D ); //定义内部定时器的设置WriteRawRC ( TPrescalerReg, 0x3E ); //设置定时器分频系数WriteRawRC ( TxAutoReg, 0x40 ); //调制发送信号为 100%ASK
}
/*
*********************************************************************************************************
* 函 数 名: PcdComMF522
* 功能说明: 通过 RC522 和 ISO14443 卡通讯
* 形 参: ucCommand, RC522 命令字
* pInData,通过 RC522 发送到卡片的数据
* ucInLenByte,发送数据的字节长度
* pOutData,接收到的卡片返回数据
* pOutLenBit,返回数据的位长度
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdComMF522 ( uint8_t ucCommand, uint8_t * pInData, uint8_t ucInLenByte, uint8_t * pOutData, uint32_t * pOutLenBit )
{char cStatus = MI_ERR;uint8_t ucIrqEn = 0x00;uint8_t ucWaitFor = 0x00;uint8_t ucLastBits;uint8_t ucN;uint32_t ul;switch ( ucCommand ){case PCD_AUTHENT: //Mifare 认证{ucIrqEn = 0x12; //允许错误中断请求 ErrIEn 允许空闲中断 IdleIEnucWaitFor = 0x10; //认证寻卡等待时候 查询空闲中断标志位}break;case PCD_TRANSCEIVE: //接收发送 发送接收{ucIrqEn = 0x77; //允许 TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEnucWaitFor = 0x30; //寻卡等待时候 查询接收中断标志位与 空闲中断标志位}break;default:break;}WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 ); //IRqInv 置位管脚 IRQ 与 Status1Reg 的 IRq 位的值相反ClearBitMask ( ComIrqReg, 0x80 ); //Set1 该位清零时, CommIRqReg 的屏蔽位清零WriteRawRC ( CommandReg, PCD_IDLE ); //写空闲命令SetBitMask ( FIFOLevelReg, 0x80 ); //置位 FlushBuffer 清除内部 FIFO 的读和写指针以及 ErrReg 的BufferOvfl 标志位被清除for ( ul = 0; ul < ucInLenByte; ul ++ ){WriteRawRC ( FIFODataReg, pInData [ ul ] ); //写数据进 FIFOdata}WriteRawRC ( CommandReg, ucCommand ); //写命令if ( ucCommand == PCD_TRANSCEIVE ){SetBitMask(BitFramingReg,0x80); //StartSend 置位启动数据发送 该位与收发命令使用时才有效}ul = 1000;//根据时钟频率调整,操作 M1 卡最大等待时间 25msdo //认证 与寻卡等待时间{ucN = ReadRawRC ( ComIrqReg ); //查询事件中断ul --;} while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) ); //退出条件 i=0,定时器中断,与写空闲命令ClearBitMask ( BitFramingReg, 0x80 ); //清理允许 StartSend 位if ( ul != 0 ){if ( ! ( ReadRawRC ( ErrorReg ) & 0x1B ) ) // 读 错 误 标 志 寄 存 器 BufferOfI CollErr ParityErrProtocolErr{cStatus = MI_OK;if ( ucN & ucIrqEn & 0x01 ) //是否发生定时器中断{cStatus = MI_NOTAGERR;}if ( ucCommand == PCD_TRANSCEIVE ){ucN = ReadRawRC ( FIFOLevelReg ); //读 FIFO 中保存的字节数ucLastBits = ReadRawRC ( ControlReg ) & 0x07; //最后接收到得字节的有效位数if ( ucLastBits ){* pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits; //N 个字节数减去 1(最后一个字节) +最后一位的位数 读取到的数据总位数}else{* pOutLenBit = ucN * 8; //最后接收到的字节整个字节有效}if ( ucN == 0 ){ucN = 1;}if ( ucN > MAXRLEN ){ucN = MAXRLEN;}for ( ul = 0; ul < ucN; ul ++ ){pOutData [ ul ] = ReadRawRC ( FIFODataReg );}}}else{cStatus = MI_ERR;}}SetBitMask ( ControlReg, 0x80 ); // stop timer nowWriteRawRC ( CommandReg, PCD_IDLE );return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: M500PcdConfigISOType
* 功能说明: 设置 RC522 的工作方式
* 形 参: ucType,工作方式
* 返 回 值: 无
*********************************************************************************************************
*/
void M500PcdConfigISOType ( uint8_t ucType )
{if ( ucType == 'A') //ISO14443_A{ClearBitMask ( Status2Reg, 0x08 );WriteRawRC ( ModeReg, 0x3D ); //3FWriteRawRC ( RxSelReg, 0x86 ); //84WriteRawRC( RFCfgReg, 0x7F ); //4FWriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)WriteRawRC ( TReloadRegH, 0 );WriteRawRC ( TModeReg, 0x8D );WriteRawRC ( TPrescalerReg, 0x3E );delay_us ( 2 );PcdAntennaOn ();//开天线}
}
/*
*********************************************************************************************************
* 函 数 名: PcdRequest
* 功能说明: 寻卡
* 形 参: ucReq_code,寻卡方式
* = 0x52,寻感应区内所有符合 14443A 标准的卡
* = 0x26,寻未进入休眠状态的卡
* pTagType,卡片类型代码
* = 0x4400, Mifare_UltraLight
* = 0x0400, Mifare_One(S50)
* = 0x0200, Mifare_One(S70)
* = 0x0800, Mifare_Pro(X))
* = 0x4403, Mifare_DESFire
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdRequest ( uint8_t ucReq_code, uint8_t * pTagType )
{char cStatus;uint8_t ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ClearBitMask ( Status2Reg, 0x08 ); //清理指示 MIFARECyptol 单元接通以及所有卡的数据通信被加密的情况WriteRawRC ( BitFramingReg, 0x07 ); // 发送的最后一个字节的 七位SetBitMask ( TxControlReg, 0x03 ); //TX1,TX2 管脚的输出信号传递经发送调制的 13.56 的能量载波信号ucComMF522Buf [ 0 ] = ucReq_code; //存入 卡片命令字cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, & ulLen ); //寻卡if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) ) //寻卡成功返回卡类型{*pTagType = ucComMF522Buf [ 0 ];*( pTagType + 1 ) = ucComMF522Buf [ 1 ];}else{cStatus = MI_ERR;}return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: PcdAnticoll
* 功能说明: 防冲撞
* 形 参: pSnr,卡片序列号, 4 字节
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdAnticoll ( uint8_t * pSnr )
{char cStatus;uint8_t uc, ucSnr_check = 0;uint8_t ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ClearBitMask ( Status2Reg, 0x08 ); //清 MFCryptol On 位 只有成功执行 MFAuthent 命令后,该位才能置位WriteRawRC ( BitFramingReg, 0x00); //清理寄存器 停止收发ClearBitMask ( CollReg, 0x80 ); //清 ValuesAfterColl 所有接收的位在冲突后被清除ucComMF522Buf [ 0 ] = 0x93; //卡片防冲突命令ucComMF522Buf [ 1 ] = 0x20;cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, & ulLen);//与卡片通信if ( cStatus == MI_OK) //通信成功{for ( uc = 0; uc < 4; uc ++ ){*( pSnr + uc ) = ucComMF522Buf [ uc ]; //读出 UIDucSnr_check ^= ucComMF522Buf [ uc ];}if ( ucSnr_check != ucComMF522Buf [ uc ] ){cStatus = MI_ERR;}}SetBitMask ( CollReg, 0x80 );return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: CalulateCRC
* 功能说明: 用 RC522 计算 CRC16
* 形 参:
* pIndata,计算 CRC16 的数组
* ucLen,计算 CRC16 的数组字节长度
* pOutData,存放计算结果存放的首地址
* 返 回 值: 无
*********************************************************************************************************
*/
void CalulateCRC ( uint8_t * pIndata, uint8_t ucLen, uint8_t * pOutData )
{uint8_t uc, ucN;ClearBitMask(DivIrqReg,0x04);WriteRawRC(CommandReg,PCD_IDLE);SetBitMask(FIFOLevelReg,0x80);for ( uc = 0; uc < ucLen; uc ++){WriteRawRC ( FIFODataReg, * ( pIndata + uc ) );}WriteRawRC ( CommandReg, PCD_CALCCRC );uc = 0xFF;do{ucN = ReadRawRC ( DivIrqReg );uc --;} while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );
}
/*
*********************************************************************************************************
* 函 数 名: PcdSelect
* 功能说明: 选定卡片
* 形 参: pSnr,卡片序列号, 4 字节
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdSelect ( uint8_t * pSnr )
{char ucN;uint8_t uc;uint8_t ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;ucComMF522Buf [ 1 ] = 0x70;ucComMF522Buf [ 6 ] = 0;for ( uc = 0; uc < 4; uc ++ ){ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );}CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );ClearBitMask ( Status2Reg, 0x08 );ucN = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, & ulLen );if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) ){ucN = MI_OK;}else{ucN = MI_ERR;}return ucN;
}
/*
*********************************************************************************************************
* 函 数 名: PcdSelect
* 功能说明: 验证卡片密码
* 形 参:
* ucAuth_mode,密码验证模式
* = 0x60,验证 A 密钥
* = 0x61,验证 B 密钥
* ucAddr,块地址
* pKey,密码
* pSnr,卡片序列号, 4 字节
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdAuthState ( uint8_t ucAuth_mode, uint8_t ucAddr, uint8_t * pKey, uint8_t * pSnr )
{char cStatus;uint8_t uc, ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ucComMF522Buf [ 0 ] = ucAuth_mode;ucComMF522Buf [ 1 ] = ucAddr;for ( uc = 0; uc < 6; uc ++ ){ucComMF522Buf [ uc + 2 ] = * ( pKey + uc );}for ( uc = 0; uc < 6; uc ++ ){ucComMF522Buf [ uc + 8 ] = * ( pSnr + uc );}cStatus = PcdComMF522 ( PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, & ulLen );if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) ){cStatus = MI_ERR;}return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: PcdWrite
* 功能说明: 写数据到 M1 卡一块
* 形 参:
* ucAddr,块地址
* pData,写入的数据, 16 字节
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdWrite ( uint8_t ucAddr, uint8_t * pData )
{char cStatus;uint8_t uc, ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ucComMF522Buf [ 0 ] = PICC_WRITE;ucComMF522Buf [ 1 ] = ucAddr;CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) ){cStatus = MI_ERR;}if ( cStatus == MI_OK ){//memcpy(ucComMF522Buf, pData, 16);for ( uc = 0; uc < 16; uc ++ ){ucComMF522Buf [ uc ] = * ( pData + uc );}CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, & ulLen );if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) ){cStatus = MI_ERR;}}return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: PcdRead
* 功能说明: 读取 M1 卡一块数据
* 形 参:
* ucAddr,块地址
* pData,读出的数据, 16 字节
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdRead ( uint8_t ucAddr, uint8_t * pData )
{char cStatus;uint8_t uc, ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ucComMF522Buf [ 0 ] = PICC_READ;ucComMF522Buf [ 1 ] = ucAddr;CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );	cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );if ( ( cStatus == MI_OK ) && ( ulLen == 0x90 ) ){for ( uc = 0; uc < 16; uc ++ )*( pData + uc ) = ucComMF522Buf [ uc ];}else{cStatus = MI_ERR;}return cStatus;
}
/*
*********************************************************************************************************
* 函 数 名: PcdHalt
* 功能说明: 命令卡片进入休眠状态
* 形 参: 无
* 返 回 值: 状态值= MI_OK,成功
*********************************************************************************************************
*/
char PcdHalt( void )
{uint8_t ucComMF522Buf [ MAXRLEN ];uint32_t ulLen;ucComMF522Buf [ 0 ] = PICC_HALT;ucComMF522Buf [ 1 ] = 0;CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );return MI_OK;
}
/***************************** 德致伦电子 DeZLinc (END OF FILE) *********************************/

RC522.h

#ifndef __BSP_RC522_H
#define __BSP_RC522_H
#include "sys.h"
/****************************************************************************/
#define RCC_ALL_RC522 ( RC522_CS_GPIO_CLK | RC522_RST_GPIO_CLK )
#define RC522_CS_GPIO_PIN GPIO_Pin_6 								//RC522_CS 引脚号
#define RC522_CS_PIN_ID 6 											//RC522_CS 引脚序号
#define RC522_CS_GPIO_PORT GPIOF 									//RC522_CS 端口号
#define RC522_CS_GPIO_CLK RCC_APB2Periph_GPIOF						//RC522_CS 时钟
#define RC522_CS_FUN_OUT PFout 										//RC522_CS 输出端口配置函数
//#define RC522_CS_FUN_IN PFin 										//RC522_CS 输入端口配置函数
#define RC522_RST_GPIO_PIN GPIO_Pin_7 								//RC522_RST 引脚号
#define RC522_RST_PIN_ID 7 											//RC522_RST 引脚序号
#define RC522_RST_GPIO_PORT GPIOB 									//RC522_RST 端口号
#define RC522_RST_GPIO_CLK RCC_APB2Periph_GPIOB 					//RC522_RST 时钟
#define RC522_RST_FUN_OUT PBout 									//RC522_RST 输出端口配置函数
//#define RC522_CS_FUN_IN PBin 										//RC522_RST 输入端口配置函数
#define RC522_SPIx SPI1 											//RC522 使用 SPI1 端口
/****************************************************************************/
//IO 操作函数
#define RC522_CS RC522_CS_FUN_OUT(RC522_CS_PIN_ID) 					//RC522_CS RC522 的片选信号
#define RC522_RST RC522_RST_FUN_OUT(RC522_RST_PIN_ID) 				//RC522_RST RC522 的复位信号

/
//MF522 命令字
/
#define PCD_IDLE 0x00 												//取消当前命令
#define PCD_AUTHENT 0x0E 											//验证密钥
#define PCD_RECEIVE 0x08 											//接收数据
#define PCD_TRANSMIT 0x04 											//发送数据
#define PCD_TRANSCEIVE 0x0C 										//发送并接收数据
#define PCD_RESETPHASE 0x0F 										//复位
#define PCD_CALCCRC 0x03 											//CRC 计算
/
//Mifare_One 卡片命令字
/
#define PICC_REQIDL 0x26 											//寻天线区内未进入休眠状态
#define PICC_REQALL 0x52 											//寻天线区内全部卡
#define PICC_ANTICOLL1 0x93 										//防冲撞
#define PICC_ANTICOLL2 0x95 										//防冲撞
#define PICC_AUTHENT1A 0x60 										//验证 A 密钥
#define PICC_AUTHENT1B 0x61 										//验证 B 密钥
#define PICC_READ 0x30 												//读块
#define PICC_WRITE 0xA0 											//写块
#define PICC_DECREMENT 0xC0 										//扣款
#define PICC_INCREMENT 0xC1 										//充值
#define PICC_RESTORE 0xC2 											//调块数据到缓冲区
#define PICC_TRANSFER 0xB0 											//保存缓冲区中数据
#define PICC_HALT 0x50 												//休眠
/
//MF522 FIFO 长度定义
/
#define DEF_FIFO_LENGTH 64 //FIFO size=64byte
#define MAXRLEN 18
/
//MF522 寄存器定义
/// PAGE 0
#define RFU00 0x00
#define CommandReg 0x01
#define ComIEnReg 0x02
#define DivlEnReg 0x03
#define ComIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define RFU0F 0x0F// PAGE 1
#define RFU10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F// PAGE 2
#define RFU20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23
#define ModWidthReg 0x24
#define RFU25 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsCfgReg 0x28
#define ModGsCfgReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F// PAGE 3
#define RFU30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define RFU3C 0x3C
#define RFU3D 0x3D
#define RFU3E 0x3E
#define RFU3F 0x3F/
//和 MF522 通讯时返回的错误代码
/
#define MI_OK 0x26
#define MI_NOTAGERR 0xcc
#define MI_ERR 0xbb
#define RC522_Dummy_Byte 0xFF/* 供外部调用的函数声明 */
void bsp_InitRc522(void);
void PcdReset ( void ); 												//复位
void M500PcdConfigISOType ( u8 type ); 									//工作方式
char PcdRequest ( u8 req_code, u8 * pTagType ); 						//寻卡
char PcdAnticoll ( u8 * pSnr); 											//读卡号
char PcdAuthState ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr );  //验证卡片密码
char PcdRead ( u8 ucAddr, u8 * pData ); 								//读卡
char PcdSelect ( u8 * pSnr );										    //选卡
char PcdHalt( void );#endif

上位机部分
在这里插入图片描述
主界面

using System;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace Wisdomclassroom
{public partial class Main : Form{SerialClass sc;SQL sql;String wendu;public Main(){this.StartPosition = FormStartPosition.CenterScreen;InitializeComponent();}private void Main_Load(object sender, EventArgs e){/*串口部分 */sc = new SerialClass("COM10", 9600);sc.openPort();sc.ReadData = Read1;/*连接数据库*/sql = new SQL("11.111.11.11", "xxxx", "xxx", "xxxxx");sql.Connect();/* 天气 API外接   json解析*/string str = API.PostWebRequest("http://apis.juhe.cn/simpleWeather/query", "city=%E5%A4%A9%E6%B4%A5&key=xxxxx");JObject json1 = JObject.Parse(str);//解析json Newtonsoft.Json.Linq.JObject class.string jieguo = json1["reason"].ToString();wendu = json1["result"]["realtime"]["temperature"].ToString();string info = json1["result"]["realtime"]["info"].ToString();string humidity = json1["result"]["realtime"]["humidity"].ToString();temp .Text = wendu;weather.Text = info;hum.Text  = humidity;int a = Convert.ToInt32(wendu);if (numericUpDown1.Value < a){bo = true;byte[] data = { 0x05 };sc.SendData(data);}else {bo = false;byte[] data = { 0x06 };sc.SendData(data);}/*启动time控件 */timer1.Start();}private void timer1_Tick(object sender, EventArgs e){/*显示系统时间、日期 */calendar.Text = DateTime.Now.ToString("yyy年MM月dd日");time.Text = DateTime.Now.ToString("HH时mm分ss秒");}public void Read(string readstr, byte[] temp){   //byte[] data = { 0x05 };//sc.SendData(data);/* 下位机体温部分 */Invoke(new MethodInvoker(delegate (){            //label1.Text = readstr+"°C";// MessageBox.Show(byteToHexStr(temp));//do something... }));}public void Read1(string readstr, byte[] card){/*读取数据库的数据 ,刷卡显示信息*/string xingming = sql.GetString(string.Format("select xingming from [login] where ID='{0}'", card));string arr = byteToHexStr(card);string sr = sql.GetString("select ID from [login] where ID='" + arr + "'");if (sr != ""){string id = sql.GetString("select ID from [login] where ID='" + arr + "'");string xm = sql.GetString("select xingming from [login] where ID='" + arr + "'");string xb = sql.GetString("select xingbie from [login] where ID='" + arr + "'");string xj = sql.GetString("select xueji from [login] where ID='" + arr + "'");MessageBox.Show("姓名:" + xm + '\n' + "性别:" + xb + '\n' + "学籍校:" + xj + '\n' + "ID:" + id+'\n'+"已打卡");}else{MessageBox.Show("卡号不存在");}}public string byteToHexStr(byte[] bytes){//字节数组转16进制字符串 string returnStr = "";if (bytes != null){for (int i = 0; i < bytes.Length; i++){returnStr += bytes[i].ToString("X2");}}return returnStr;}private void Main_Activated(object sender, EventArgs e){/*RFID刷卡、打开串口*/sc = new SerialClass("COM10", 9600);sc.openPort();sc.ReadData = Read1;}private void openled_Click(object sender, EventArgs e){/* 开下位机灯  */// byte[] data = { 0xfd, 0x03, 0x07, 0x04, 0x01, 0x60, 0xdf };byte[] data = { 0x03 };sc.SendData(data);MessageBox.Show("教室灯光已开");}private void panel3_Click(object sender, EventArgs e){/* 关下位机灯  *///  byte[] data = { 0xfd, 0x03, 0x07, 0x04, 0x02, 0x60, 0xdf };byte[] data = { 0x04};sc.SendData(data);MessageBox.Show("教室灯光已关");}private void panel2_MouseUp(object sender, MouseEventArgs e){//效果:按下颜色变暗}private void panel4_Click(object sender, EventArgs e){/*温度阈值判断,温度大于阈值开下位机风扇,温度小于阈值关风扇*/int a = Convert.ToInt32(wendu);if (numericUpDown1.Value < a){byte[] data = { 0x05 };sc.SendData(data);MessageBox.Show("风扇已开");}else{byte[] data = { 0x06 };sc.SendData(data);MessageBox.Show("温度低于阈值");             }}private void Media_off_Click(object sender, EventArgs e){//关下位机风扇byte[] data = { 0x06 };sc.SendData(data);MessageBox.Show("风扇已关");}private void panel5_Click(object sender, EventArgs e){//开下位机蜂鸣器byte[] data = { 0x07 };sc.SendData(data);MessageBox.Show("音箱已开");}private void panel6_Click(object sender, EventArgs e){//开下位机舵机byte[] data = { 0x01};sc.SendData(data);MessageBox.Show("教室窗户已开");}private void win_off_Click(object sender, EventArgs e){//关下位机舵机byte[] data = { 0x02 };sc.SendData(data);MessageBox.Show("教室窗户已关");}private void beep_off_Click(object sender, EventArgs e){//关下位机蜂鸣器byte[] data = {0x08};sc.SendData(data);}private void panel1_Click(object sender, EventArgs e){/* 跳转表单 退出线程 */Form f1 = new DataSheet();this.Hide();f1.ShowDialog();Application.ExitThread();}/**/private void panel5_Click_1(object sender, EventArgs e){/*跳转登录 退出线程*/Form f = new denglu();this.Hide();f.ShowDialog();Application.ExitThread();}private void Main_Deactivate(object sender, EventArgs e){sc.closePort();}private void Main_Activated_1(object sender, EventArgs e){sc.openPort();}bool bo;private void numericUpDown1_ValueChanged(object sender, EventArgs e){/*温度阈值判断,温度大于阈值开下位机风扇,温度小于阈值关风扇*/int a = Convert.ToInt32(wendu);if (numericUpDown1.Value < a){byte[] data = { 0x05 };sc.SendData(data);if (bo==false){ MessageBox.Show("温度高于阈值,风扇已开");bo = true;}}else{byte[] data = { 0x06 };sc.SendData(data);if (bo == true){ MessageBox.Show("温度低于阈值,风扇已关闭");bo = false;byte[] data1 = { 0x07 };sc.SendData(data1);}}}}
}

表单部分
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;namespace Wisdomclassroom
{public partial class DataSheet : Form{SQL sql;public DataSheet(){this.StartPosition = FormStartPosition.CenterScreen;InitializeComponent();}private void DataSheet_Load(object sender, EventArgs e){sql = new SQL("11.111.11.11", "xxxxxx", "xxx", "xxxxx");sql.Connect();}private void button1_Click(object sender, EventArgs e){string connstr = @"Data Source=11.111.11.11;Initial Catalog=xxxxxx;Uid=xxx;Pwd=xxxxx";saveFileDialog1.Filter = "文本文件|*.txt";if (saveFileDialog1.ShowDialog() == DialogResult.OK){string path = saveFileDialog1.FileName;using (SqlConnection conn = new SqlConnection(connstr)){string sql1 = "select xingming,ID,xueji from [login]";using (SqlCommand cmd = new SqlCommand(sql1, conn)){conn.Open();using (SqlDataReader dr = cmd.ExecuteReader()){List<string> student = new List<string>();while (dr.Read()){string num = dr["ID"].ToString();string name = dr["xingming"].ToString();string school = dr["xueji"].ToString();student.Add( "姓名:"+name+ "  "+"学号:"+num+"   "+"学籍校:"+ school) ;}File.WriteAllLines(path, student.ToArray());MessageBox.Show("导出成功");}}}}}private denglu anotherForm;private void 退出ToolStripMenuItem_Click(object sender, EventArgs e){anotherForm = new denglu();this.Hide();anotherForm.ShowDialog();Application.ExitThread();}private zhuce anotherForm1;private void 个人信息录入ToolStripMenuItem_Click(object sender, EventArgs e){anotherForm1 = new zhuce();this.Hide();anotherForm1.ShowDialog();Application.ExitThread();}private wangjimima anotherForm2;private void 修改密码ToolStripMenuItem_Click(object sender, EventArgs e){anotherForm2 = new wangjimima();this.Hide();anotherForm2.ShowDialog();Application.ExitThread();}private void 清空数据库ToolStripMenuItem_Click(object sender, EventArgs e){String str = sql.GetString("delete from [login]");MessageBox.Show("数据库已清空");}}
}

总结:

由于本项目应用到了硬件,主要通过串口将上位机C#和下位机stm32进行通信,上位机通过发送协议数据给下位机,数据传输完成,下位机判断不同的数据,响应执行串口中断函数,实现不同的功能。而串口通信在传输协议里并不是最优的选择,所以我想在以后项目用到Wi-Fi或Zigbee协议等,来提升自己的水平。

技术问题:

硬件层面上:

项目初期,在实现单独人体红外测温模块,下位机能够正常响应,能够接收到正常温度的发送。

项目中期阶段,其他外设的加入,导致硬件引脚的冲突,例如下位机板载的灯环用到了PB6引脚及RFID模块的PB7引脚,在板载外设不能更改的情况下,先是将红外测温模块底层代码的数据线和时钟线引脚进行修改,但还是读不到正确的温度。

项目后期阶段,在保证核心功能RFID的实现下,权衡将红外模块去除,加入执行器风扇,通过和阈值温度的判断,实现自动开关,其也是较为创新的地方。

软件层面上:

C#核心问题:

在上位机C#在项目快结束时一直存在的问题,其下位机RFID,通过串口将电子标签的ID发送给上位机,上位机里的串口类,当接收到一个字节时,也会触发DataReceived事件,同时调用Invoke函数,将卡号显示的textbox里,其只有第一次刷的卡号才能显示,再刷传输来的数据就会溢出或不正确。
经过老师指导,在每次的刷卡之后接收到数据,可以用clear将上次传过来的数据清除,保证每次的数据帧的正确,但这个串口类调用不了clear,所以转换思路,通过设置缓存区的方式,将传过来的数据的帧头和结束符做一个判断,将其放入线程里,将其实现数据的传输的正确性。
问题解决思路的不同,也导致项目后期工作量不同、业务逻辑不同。后来在下位机中,将电子标签一靠近RFID,就会一直读改为读一次。最后也是通过简单的方法解决复杂的问题。

可加本人Q1429536866,欢迎大家指导讨论。


http://chatgpt.dhexx.cn/article/pf0900yE.shtml

相关文章

基于stm32电梯管理系统设计

基于stm32电梯管理系统设计 这里记录一下以前自己做的嵌入式课程设计&#xff0c;报告中的图片和文字太多了&#xff0c;全部一个一个把搬过来太麻烦了,需要完整文本和代码自行主页私我 摘要关键词一、课题概述1.1市场调研1.2 需求分析 二、课题实施方案2.1 硬件总体方案2.2 性…

基于Xilinx的Kintex-7系列XC7K325T的硬件加速卡

产品型号: B-PCIE-K7F5XILINX的Kintex-7系列FPGA处理器 B-PCIE-K7F5是一款基于PCI Express总线架构的高性能FPGA算法加速卡&#xff0c;该板卡采用Xilinx的高性能28nm 7系列FPGA作为运算节点。Xilinx的28nm 7系列FPGA通过对资源、接口以及时钟的优化&#xff0c;在高性能计算&a…

基于STM32设计的车库监控报警系统

一、前言 随着社会的发展,人们的生活水平不断提高对安防问题的关注度越来越高,因而各类防盗设备也层出不穷,本文采用红外测距传感器、摄像头、STM32单片机以及ESP8266无线通信模块设计一种车库防盗报警器,其可安装在车库的里,通过红外线测距检测是否有人入侵,产生报警信号…

dnw驱动更新,支持全系统(xp,win7,win8/win10)

前言: 本文用于解决win7以上系统使用dnw难装驱动问题&#xff0c;使用新驱动: zadig-2.3.exe&#xff0c;支持xp&#xff0c;win7/win8/win10系统&#xff0c;安装方便、高效&#xff0c;欢迎试用。 对于裸板开发&#xff0c;我们一般使用JTAG工具&#xff0c;比如OpenJTAG、…

jz2440s3c2440 jtag口、串口、usb devices 使用

1.串口&#xff1a; 串口类型&#xff1a; 针串口 、usb串口的使用 1. usb 串口 插入电脑&#xff0c;计算机上设备管理器中其他设备下出现新设备 设备管理器 中查看 2. 安装串口驱动 &#xff0c;安装驱动以后 系统分配com4 串口 3. windows下载串口连接软件 MobaXterm&…

基于STM32设计的城市绿化云端监控系统(华为云IOT)

一、设计需求 1.1 项目背景 随着科技的蓬勃发展改变了很多传统行业的作业方式,当我们用移动支付代替现金交易时,当我们足不出户就能满足饥饿的身体时,我们的生活方式因为科技而发生了改变;同样科技也在改变着我们周围的点点滴滴,城市绿化养护亦是如此。 通过智慧控制系统…

FPGA的调试-虚拟JTAG

对于FPGA调试&#xff0c;主要以Intel FPGA为例&#xff0c;在win10 Quartus ii 17.0环境下进行仿真和调试&#xff0c;开发板类型EP4CE15F17。主要包括一下几个部分&#xff1a; - FPGA的调试-虚拟JTAG&#xff08;Virtual JTAG&#xff09; - FPGA的调试-在线存储器内容编辑…

Win7、Win8、Win10系统USB-Blaster驱动程序无法安装的解决办法

这篇博文是我转载dezhihuang的博文&#xff0c;原文名称和地址如下&#xff0c;并对内容做了适当调整&#xff1a; [原]Win7、Win8系统USB-Blaster驱动程序无法安装的解决办法 第一次用Markdown编辑博客&#xff0c;格式方面真是捉急啊&#xff01; Win7、Win8、Win10操作系…

avr+开发环境+linux,win7下avr单片机开发环境的搭建

操作系统&#xff1a;win7 professional x86 开发软件&#xff1a;avr studio 4.19 首先下载avr studio 4.19&#xff0c;因为貌似这是atmel官方最后支持jtag ice的开发环境。而且也就只有这个4的版本才支持win7&#xff0c;正好本人有个jtag&#xff0c;所以果断选择这个版本…

IBM Spectrum LSF RTM

IBM Spectrum LSF RTM IBM Spectrum LSF RTM是IBM Spectrum LSF环境的操作仪表板&#xff0c;提供全面的工作负载监视、报告和管理。它使集群管理员在日常活动中更加高效&#xff0c;并提供所需的信息和工具&#xff0c;以提高集群效率&#xff0c;实现更好的用户生产力&#…

IBM Spectrum LSF Suites

IBM Spectrum LSF Suites 高性能计算(HPC)不再仅仅适用于大型组织和技术熟练的用户。在当今竞争激烈的商业环境中&#xff0c;几乎每个行业都需要更短的设计周期和更高质量的结果&#xff0c;HPC适用于任何规模的组织。它是为那些需要从大量数据中进行分析和回答的用户而设计的…

LSF_SPAN

span字符串指定并行作业运行的位置。如果省略span, LSF将从可用的处理器中为作业分配所需的处理器。 一、语法 span[host1]&#xff1a;指示分配给作业的处理器必须位于同一个主机上。 span[blockvalue]&#xff1a;对并行作业来说&#xff0c;LSF将根据block size来分配slot…

集群调度LSF-学习笔记

集群-------多台设备 HPC集群----多台用于计算的设备 集群调度-LSF&#xff1a;LSF 是一种强大的工作负载管理平台&#xff0c;提供基于各种策略的智能调度功能&#xff0c;利用分布式的基础架构资源来提高整体的系统性能。用户通过 LSF可以实现集群间的负载均衡&#xff0c;扩…

IBM Platform LSF在IC行业内的使用

LSF在&#xff29;&#xff23;设计中有哪些值得匹配的 1、管理低利用率Job •针对short normal这类队列&#xff0c;查询20分钟以后&#xff0c;Job利用率依然很低的Job信息。 •$bjobs -u all -q short -o ‘id user queue stat ugroup first_host sla idle_factor slots …

IBM Spectrum LSF-手册

在所有规模的企业中&#xff0c;应用程序能力和数据量持续显著增长&#xff0c;推动了对更多计算能力和高性能管理和分析工具的需求。即使在传统的高性能计算(HPC)环境中&#xff0c;多个计算竖井、不均匀处理、设计周期泄漏和延迟结果也是常见的。面对日益严格的经济压力&…

LSF - 提交GUI应用到LSF无法运行,报错Failed to connect to socket /tmp/dbus-xxxxxxxxx: Connection refused

问题描述 提交GUI应用到LSF无法运行&#xff0c;如下所示 问题分析 这种GUI应用&#xff0c;不能以交互式的方式提交。提交命令换成bsub firefox即可。

LSF的使用方法总结

一、LSF 基本介绍 LSF&#xff08;Load Sharing Facility&#xff09;是IBM旗下的一款分布式集群管理系统软件&#xff0c;负责计算资源的管理和批处理作业的调度。它给用户提供统一的集群资源访问接口&#xff0c;让用户透明地访问整个集群资源。同时提供了丰富的功能和可定制…

IBM Spectrum LSF

IBM Spectrum LSF IBMSpectrum LSF系列是对用于高性能计算(HPC)环境的工作负载管理解决方案有一个完整的组合。具有全面的智能配套调度能力&#xff0c;它有助于确保正确的资源自动分配到正确的作业&#xff0c;最大限度地提高应用程序性能和效率。具有强大的管理功能和无与伦…

LSF - 集群概览

LSF - 集群概览 LSF - 术语与概念 Job状态 PEND 在队列中等待调度和调度的。RUN 发送到主机并运行。DONE 正常结束与零退出值。EXIT 以非零退出值结束。PSUSP 当作业挂起时挂起。USUSP 被用户挂起。SSUSP 被LSF系统挂起。POST_DONE 后处理完成&#xff0c;没有错误。POST_ER…

LSF集群搭建笔记

LSF-linux_amd64集群搭建记录 修改节点ip地址为静态ip安装并开启ssh服务修改主机名修改/etc/hosts文件(为了方便所有机器都要改)设置集群间ssh免密钥通信(如果想root间无需密码登陆需要设置了所有机器可以root登陆&#xff0c;并改root密码为固定密码&#xff0c;默认root密码每…