利用STM32制作紅外測溫儀之軟件設計(MLX90614)

目錄

        • (一)工程目錄如圖:
        • (二)main函數實現:
        • (三)MLX90614測溫代碼實現

前面介紹了使用 STM32制作紅外測溫儀硬件設計,今天來說一下軟件的實現,具體的程序,完整的keil代碼我已經打包放在了這里 MLX90614紅外測溫儀軟件設計.rar
由于程序流程比較清晰,這里我就不把程序流程圖貼出來了,直接上代碼。

(一)工程目錄如圖:

圖一

(二)main函數實現:

/*******************************************************
*文件名:    main.c
*作  者:    水枂:https://me.csdn.net/download/weixin_43839785
*生成日期:   2019/1/2
*最后修改:
*功能描述: 紅外溫度測量
********************************************************/
#include "varytypes.h"extern unsigned char image[];
extern char envirTemp[][32];
extern char objectTemp[][32];
extern char historyTemp_max[][32];
extern char historyTemp_min[][32];
extern unsigned char flag;
u16  volatile  arr[2]={0,100};
int main(void)
{delay_init();//延時函數初始化NVIC_Configuration();//設置NVIC中斷分組0~4共5組 :2位搶占優先級,2位響應優先級 		BlueTooth_Init();//藍牙初始化USART2_Init();//串口藍牙初始化LED_Init();//初始化LED端口PC13KEY_Init();//初始化按鍵端口PA0OLED_Init();//初始化oledOLED_Clear();//清屏RTCInit();//RTC時鐘初始化AT24CXX_Init();//AT24C04存儲初始化MLX_I2C_Init();//Mlx90614讀取初始化/****************************************
*溫度記錄值讀取
******************************************/	
//	arr[0]=AT24CXX_ReadOneByte(0);//max
//	arr[1]=AT24CXX_ReadOneByte(1);//min/****************************************
*開機界面顯示
******************************************/OLED_ShowString(3,1,"welcome");OLED_DrawBMP(77, 1,128, 6,image);OLED_ShowString(3,4,"waiting.");delay_s(1);OLED_ShowString(3,4,"waiting..");delay_s(1);OLED_ShowString(3,4,"waiting...");delay_s(1);OLED_Clear();while(1){KEY_Scan();if(flag==0){OLED_ShowCHinese_Mul(3,1,5,objectTemp);display_temp(75,1,OBJ1TEMPADDR);OLED_ShowCHinese_Mul(3,5,5,envirTemp);display_temp(75,5,ENVITEMPADDR);}else if(flag==1){OLED_ShowCHinese_Mul(1,1,7,historyTemp_max);OLED_ShowNum(105,1,AT24CXX_ReadOneByte(0),3,16);OLED_ShowCHinese_Mul(1,5,7,historyTemp_min);OLED_ShowNum(105,5,AT24CXX_ReadOneByte(1),3,16);}}	
}/****************************************************
*函數名   :display_temp
*功 能    :顯示采集回來轉換后的溫度
*參 數    : @ x,y :起點坐標	 // @object: 是環境溫度還是物體溫度ENVITEMPADDR、OBJ1TEMPADDR、OBJ2TEMPADDR
*說 明    :Temperature data is T=(Data)*0.02-273.15運用了這個的轉換公式計算溫度
*****************************************************/
void display_temp(u8 x,u8 y,u8 object)
{u16  temp,T;u8 point_before,point_after;u8 point_after_one ,point_after_two;temp=I2C_ReadRAM(0x00,object);//0x00是器件的地址,由于只有一個用了0x00T=temp*2;if(T>=27315) //溫度:零上{T=T-27315;point_before=T/100;point_after=T-point_before*100;point_after_one=point_after/10;//為了小數點后顯示正常point_after_two=point_after%10;OLED_ShowNum(x,y,point_before,3,16);OLED_ShowString(x+24,y,".");OLED_ShowNum(x+32,y,point_after_one,1,16);OLED_ShowNum(x+40,y,point_after_two,1,16);if(object==OBJ1TEMPADDR){if(point_before>arr[0]){arr[0]=point_before;}//arr[0]存放溫度最高值if(point_before<arr[1]){arr[1]=point_before;}//arr[1]存放溫度最低值}}else//溫度:零下{T=27315-T;point_before=T/100;point_after=T-point_before*100;OLED_ShowString(x,y,"-");OLED_ShowNum(x+8,y,point_before,3,16);OLED_ShowString(x+32,y,".");OLED_ShowNum(x+40,y,point_after,2,16);}  	}

(三)MLX90614測溫代碼實現

關于MLX90614的文檔,可以直接百度,或者去淘寶賣家那要一份,MLX90614測溫代碼實現:

/**
******************************************************************************
*
* 基于STM32F103的MLX90614紅外溫度傳感器驅動程序
*
*******************************************************************************/
#include "mlx90614.h"/**
* @功能 I2C通信狀態改變后的延時
* @說明 無
* @參數 無
* @返回值 無
*/
void I2C_Delay(void)
{
delay_us(5);
}
/****************************************************************
*初始化MLX_IIC用的端口
****************************************************************/
void MLX_I2C_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);;//使能 GPIOB 時鐘//GPIOB6,B7初始化設置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;//推挽模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);//初始化MLX_IIC_SCL=1;MLX_IIC_SDA=1;	}
/*******************************************************************************
* 函 數 名         : SDA_OUT
* 函數功能		   : SDA輸出配置	   
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void MLX_SDA_OUT(void)
{GPIO_InitTypeDef  GPIO_InitStructure;//GPIOB9初始化設置GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;//推挽模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHzGPIO_SetBits(GPIOB,GPIO_Pin_7);	//上拉GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}/*******************************************************************************
* 函 數 名         : SDA_IN
* 函數功能		   : SDA輸入配置	   
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void MLX_SDA_IN(void)
{GPIO_InitTypeDef  GPIO_InitStructure;//GPIOB9初始化設置GPIO_InitStructure.GPIO_Pin =GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//輸入模式GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}/**
* @功能 產生通訊開始信號
* @說明 MLX90614在SCK=1時,檢測到SDA由1到0表示通信開始
* @參數 無
* @返回值 無
*/
void I2C_Start(void)
{
MLX_SDA_OUT();
MLX_IIC_SDA=1;
MLX_IIC_SCL=1;
I2C_Delay();
MLX_IIC_SDA=0;
I2C_Delay();
MLX_IIC_SCL=0;
I2C_Delay();
}
/**
* @功能 產生通訊停止信號
* @說明 MLX90614在SCK=1時,檢測到SDA由0到1表示通信結束
* @參數 無
* @返回值 無
*/
void I2C_Stop(void)
{
MLX_SDA_OUT();
MLX_IIC_SDA=0;
MLX_IIC_SCL=0;
I2C_Delay();
MLX_IIC_SCL=1;
I2C_Delay();
MLX_IIC_SDA=1;
I2C_Delay();
}/*******************************************************************************
* 函 數 名         : IIC_Ack
* 函數功能		   : 產生ACK應答  
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void I2C_Ack(void)
{MLX_IIC_SCL=0;MLX_SDA_OUT();MLX_IIC_SDA=0;delay_us(2);MLX_IIC_SCL=1;delay_us(5);MLX_IIC_SCL=0;
}/*******************************************************************************
* 函 數 名         : IIC_NAck
* 函數功能		   : 產生NACK非應答  
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/		    
void I2C_NAck(void)
{MLX_IIC_SCL=0;MLX_SDA_OUT();MLX_IIC_SDA=1;delay_us(2);MLX_IIC_SCL=1;delay_us(5);MLX_IIC_SCL=0;
}	/*******************************************************************************
* 函 數 名         : IIC_Wait_Ack
* 函數功能		   : 等待應答信號到來   
* 輸    入         : 無
* 輸    出         : 1,接收應答失敗0,接收應答成功
*******************************************************************************/
u8 I2C_Wait_Ack(void)
{u8 tempTime=0;MLX_SDA_IN();      //SDA設置為輸入  MLX_IIC_SDA=1;delay_us(1);	   MLX_IIC_SCL=1;delay_us(1);	 while(MLX_READ_SDA){tempTime++;if(tempTime>250){I2C_Stop();return 1;}}MLX_IIC_SCL=0;//時鐘輸出0 	   return 0;  
} /**
* @功能 將MLX90614的工作模式從PWM模式切換到SMBus模式
* @說明 從PWM模式切換到SMBus的方法是將SCL保持至少1.44ms以上的低電平
* 如果PWM沒有使能就不需要發送請求命令
* @參數 無
* @返回值 無
*/
void PwmToSMBus(void)
{
MLX_IIC_SCL=0;
delay_us(1500); //大于1.44ms
MLX_IIC_SCL=1;
}
/**
* @功能 退出睡眠模式
* @說明 保持SCK高電平后,SDA持續至少33ms低電平,
* 在退出睡眠模式后需要間隔250ms(典型值)才輸出數據。
* @參數 無
* @返回值 無
*/
void Eixt_Sleep(void)
{
MLX_IIC_SCL=1;
MLX_IIC_SDA=1;
I2C_Delay();
MLX_IIC_SDA=0;
delay_ms(35); //大于33ms退出睡眠模式
MLX_IIC_SDA=1;
delay_ms(260); //大于250ms開始輸出數據
}
/**
* @功能 從RAM/EEPROM中讀取一個字節數據
* @說明 從MLX90614中的指定地址讀取一個字節數據,高位在前,低位在后
* @參數 ack_nack:主機應答信號
* @返回值 dat: 讀取的數據
*/
uint8_t I2C_ReadByte(uint8_t ack)
{u8 i,receive=0;MLX_SDA_IN();//SDA設置為輸入for(i=0;i<8;i++ ){MLX_IIC_SCL=0; delay_us(2);MLX_IIC_SCL=1;receive<<=1;if(MLX_READ_SDA)receive++;   delay_us(1); }					 if (!ack)I2C_NAck();//發送nACKelseI2C_Ack(); //發送ACK   return receive;
}
/**
* @功能 向EEPROM寫一個字節數據
* @說明 在寫完一個字節后檢測MLX6014是否發送了應答信號
* @參數 dat:需要發送的字節
* @返回值 s_ack:應答信號狀態
*/
uint8_t I2C_WriteByte(uint8_t dat)
{u8 t;   uint8_t s_ack=0;MLX_SDA_OUT(); 	    MLX_IIC_SCL=0;//拉低時鐘開始數據傳輸for(t=0;t<8;t++){              if((dat&0x80)>0) //0x80  1000 0000MLX_IIC_SDA=1;elseMLX_IIC_SDA=0;dat<<=1; 	  delay_us(2);   //對TEA5767這三個延時都是必須的MLX_IIC_SCL=1;delay_us(2); MLX_IIC_SCL=0;	delay_us(2);}	 
if(I2C_Wait_Ack()) //高電平表示正確接收數據  (高?低??這個應該是低電平)
{
s_ack = ACK_FAIL;
}
else
{
s_ack = ACK_SUCCESS;
}
//delay_us(2*N);//修改的
//MLX_IIC_SCL=0;	
//delay_us(4*N);
return s_ack;
}
/**
* @功能 讀MLX90614的RAM中內容
* @說明 主要讀取三個,環境溫度,物體溫度1,物體溫度2
* 器件從地址可以通過向EEPROM的SMBus地址0x0E中寫入來進行設定。
* @參數 saddr:從機地址,7位地址,任何MLX90614都會對0x00地址作出反應
* cmd:存放溫度的寄存器地址
* @返回值 Data:讀取出來的數值
*using Read Word: SA(write) - Command - SA(read) - LSByte - MSByte - PEC
*/
uint16_t I2C_ReadRAM(uint8_t saddr,uint8_t cmd)
{
uint16_t Data;
uint8_t DataL; //接收數據低字節
uint8_t DataH; //接收數據高字節
uint8_t PEC;
uint8_t retry = 10; //失敗重復次數
uint8_t s_ack = 0;
uint8_t Pecreg; //計算的PEC值
uint8_t buf[6]; //存儲已接收數據的緩存
MLX_IIC_SCL=0;	
while(retry--)
{
I2C_Start(); //發送起始位
s_ack = I2C_WriteByte((saddr<<1)|WR); //發送從機地址和Wr位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(RAM|cmd);
//發送命令,8位,RAM表示對RAM操作,cmd表示操作RAM的地址
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
I2C_Start(); //重新發送起始位
s_ack = I2C_WriteByte((saddr<<1)+1); //發送從機地址和Rd位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
DataL = I2C_ReadByte(1); //讀數據低字節
DataH = I2C_ReadByte(1); //讀數據高字節
PEC = I2C_ReadByte(1); //讀數據PEC字節
// DataL=RX_byte(0); //
// DataH=RX_byte(0); //
// PEC=RX_byte(1);
I2C_Stop(); //發送停止位
buf[5]=(saddr<<1);
buf[4]=EEPROM|cmd;
buf[3]=(saddr<<1)|RD;
buf[2]=DataL;
buf[1]=DataH;
buf[0]=0;
Pecreg=PEC_Cal(buf,6); //調用計算 PEC 的函數
if(Pecreg == PEC)
{
break; //退出循環
}
}
else goto stop_rr;
}
else goto stop_rr;
}
else goto stop_rr;
stop_rr:
I2C_Stop(); //發送停止位,芯片接收失敗
}
PEC = PEC+1;
Data = (DataH<<8) + DataL;
return Data;
}
/**
* @功能 清除EEPROM指定單元的數據
* @說明 在向EEPROM中寫入數據之前必須先清除內存單元中的數據,也就是全部寫入0
* @參數 saddr:從機地址
cmd:發送命令
* @返回值 無
*/
void I2C_ClearEEPROM(uint8_t saddr,uint8_t cmd)
{
uint8_t retry = 10; //失敗重復次數
uint8_t s_ack = 0;
MLX_IIC_SCL=0;	
while(retry--)
{
I2C_Start(); //發送起始位
s_ack = I2C_WriteByte((saddr<<1)|WR); //發送從機地址和Wr位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(EEPROM|cmd);
//發送命令,8位 EPROM表示對RAM操作,cmd表示操作EEPROM的地址$MLX90614.C
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(0x00); //發送低字節
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(0x00); //發送高字節
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(0x6f); //發送PEC字節
if(s_ack == ACK_SUCCESS)
{
I2C_Stop(); //發送停止位
break; //退出循環
}
else goto stop_ce;
}
else goto stop_ce;
}
else goto stop_ce;
}
else goto stop_ce;
}
else goto stop_ce;
stop_ce:
I2C_Stop(); //發送停止位,芯片接收失敗
}
delay_ms(5); //擦除完成至少等待5ms
}
/**
* @功能 讀EEPROM指定單元的數據
* @說明 從指定從機讀取指定EEPROM地址的數據
* @參數 saddr:從機地址
cmd:讀取EEPROM地址
* @返回值 Data:讀取數據
*/
uint16_t I2C_ReadEEPROM(uint8_t saddr,uint8_t cmd)
{
uint8_t retry = 10;
uint8_t s_ack;
uint16_t Data;
uint8_t DataL; //接收數據低字節
uint8_t DataH; //接收數據高字節
uint8_t PEC; //接收的PEC值
uint8_t Pecreg; //計算的PEC值
uint8_t buf[6]; //存儲已接收數據的緩存
while(retry--)
{
I2C_Start(); //發送起始位
s_ack = I2C_WriteByte((saddr<<1)|WR); //發送從機地址和Wr位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(EEPROM|cmd); //發送命令
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
I2C_Start(); //重新發送起始位
s_ack = I2C_WriteByte((saddr<<1)|RD); //發送從機地址和Rd位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
DataL = I2C_ReadByte(1); //讀數據低字節
DataH = I2C_ReadByte(1); //讀數據高字節
PEC = I2C_ReadByte(1); //讀數據PEC字節
I2C_Stop(); //發送停止位
buf[5]=(saddr<<1);
buf[4]=EEPROM|cmd;
buf[3]=(saddr<<1)|RD;
buf[2]=DataL;
buf[1]=DataH;
buf[0]=0;
Pecreg=PEC_Cal(buf,6); //調用計算 PEC 的函數
if(Pecreg == PEC)
{
break;
}
}
else goto stop_re;
}
else goto stop_re;
}
else goto stop_re;
stop_re:
I2C_Stop();
}
Data = (DataH<<8) + DataL;
return Data;
}
/**
* @功能 寫EEPROM指定單元的數據
* @說明 在向EEPROM中寫入數據之前必須先清除內存單元中的數據,也就是全部寫入0
* @參數 saddr:要清除數據的內存單元
* @返回值 無
*/
void I2C_WriteEEPROM(uint8_t saddr,uint8_t cmd,uint8_t DataL,uint8_t DataH)
{
uint8_t retry = 10; //失敗重復次數
uint8_t s_ack = 0;
uint8_t Pecreg; //存儲計算所得PEC結果$MLX90614.C
uint8_t buf[6]; //存儲將要發送字節的緩沖器
buf[5]=0;
buf[4]=saddr<<1;
buf[3]=cmd;
buf[2]=DataL;
buf[1]=DataH;
buf[0]=0;
Pecreg=PEC_Cal(buf,6);
MLX_IIC_SCL=0;	
while(retry--)
{
I2C_Start(); //發送起始位
s_ack = I2C_WriteByte((saddr<<1)|WR); //發送從機地址和Wr位
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(EEPROM|cmd); //發送命令
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(DataL); //發送低字節
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(DataH); //發送高字節
if(s_ack == ACK_SUCCESS)
{
s_ack = 0;
s_ack = I2C_WriteByte(Pecreg); //發送PEC碼
if(s_ack == ACK_SUCCESS)
{
I2C_Stop(); //發送停止位
break; //退出循環
}
else goto stop_we;
}
else goto stop_we;
}
else goto stop_we;
}
else goto stop_we;
}
else goto stop_we;
stop_we:
I2C_Stop();
}
delay_ms(5); //寫入之后等待5ms
}
/**
* @功能 計算PEC包裹校驗碼,根據接收的字節計算PEC碼
* @說明 計算傳入數據的PEC碼
* @參數 pec[]:傳入的數據
n:傳入數據個數
* @返回值 pec[0]:計算得到的PEC值
*/
uint8_t PEC_Cal(uint8_t pec[],uint16_t n)
{
unsigned char crc[6];
unsigned char Bitposition=47;
unsigned char shift;
unsigned char i;
unsigned char j;
unsigned char temp;
do{
crc[5]=0; //載入 CRC數值 0x000000000107
crc[4]=0;
crc[3]=0;
crc[2]=0;
crc[1]=0x01;
crc[0]=0x07;
Bitposition=47; //設置Bitposition的最大值為47
shift=0;
//在傳送的字節中找出第一個“1”
i=5; //設置最高標志位 (包裹字節標志)
j=0; //字節位標志,從最低位開始
while((pec[i]&(0x80>>j))==0 && (i>0))
{
Bitposition--;
if(j<7)
{
j++;
}
else
{
j=0x00;
i--;
}
}//while語句結束,并找出Bitposition中為“1”的最高位位置
shift=Bitposition-8;
//得到CRC數值將要左移/右移的數值“shift”
//對CRC數據左移“shift”位
while(shift)
{
for(i=5;i<0xFF;i--)
{
if((crc[i-1]&0x80) && (i>0))
//核對字節的最高位的下一位是否為"1"
{ //是 - 當前字節 + 1
temp=1; //否 - 當前字節 + 0
} //實現字節之間移動“1”
else
{
temp=0;
}
crc[i]<<=1;
crc[i]+=temp;
}
shift--;
}
//pec和crc之間進行異或計算
for(i=0;i<=5;i++)
{
pec[i]^=crc[i];
}
}while(Bitposition>8);
return pec[0]; //返回計算所得的crc數值
}
/**
* @功能 設定MLX90614器件地址
* @說明 器件從地址可以通過向EEPROM的SMBus地址0x0E中寫入來進行設定。
為了給從器件設定地址,必須先以0x00+Wr當作從地址開始,當主機
發送此命令,MLX90614總是會反饋并忽略掉內部芯片編碼信息。
向EEPROM寫入數據前需要清除原來的數據,就是向修改單元寫入0x0000
擦除之后需要等待5ms才可以重新寫入數據
修改地址時寫入的地址高字節MLX90614會忽略
修改之后需要重新將MLX90614的電源斷開重啟。
* @參數 soaddr:從機舊地址
snaddr:從機新地址
* @返回值 無
*/
void I2C_SetSlaveAddr(uint8_t soaddr,uint8_t snaddr)
{
// uint8_t cmd = EEPROM|SMBUSADDR;
// uint8_t DataL = snaddr;
// uint8_t DataH = 0x00;
// EEPROM_WRITE(snaddr,cmd,0x00,0x00);
// EEPROM_WRITE(snaddr,cmd,DataL,DataH);
}/*************************************************
*函數名   :  CALTEMP()
*功 能    : 把讀回來的數據轉換為攝氏度
*說 明    : 從RAM里面讀出來的是一個比較大的數(可以用顯示屏打印出來看看)需要使用下面的公式把溫度轉換出來://Temperature data is T=(Data)*0.02-273.15
*參 數    : TEMP為要轉換的數據         
*修改時間 : 2019/3/15***************************************************/
void CALTEMP(unsigned long int TEMP)
{unsigned long int T;unsigned int A, B;//unsigned int tempb;T=TEMP*2;if(T>=27315) //溫度:零上{T=T-27315;A=T/100;B=T-A*100;}else//溫度:零下{T=27315-T;A=T/100;B=T-A*100;}  
}

程序這一部分不做過多的講解,關于測溫的功能都是按照官方提供的文檔進行編寫的,需要自己好好參悟,最后說一下,這個MLX90614測溫很容易受外界環境的干擾,需要自己寫算法,在硬件上進行改進才能得到更高的準確度。


本文章僅供學習交流用禁止用作商業用途,文中所有內容均為原創未經授權不得轉載

微信公眾號:zhjj0729

微博:文藝to青年

簡書:水枂

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531426.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows下使用Dev-C++開發基于pthread.h的多線程程序

一、下載Windows版本的pthread 目前最新版本是&#xff1a;pthreads-w32-2-9-1-release.zip。 二、解壓pthread到指定目錄 我選擇的目錄是&#xff1a;E:\DEV-CPP\Pthread完成后&#xff0c;該目錄會多出三個文件夾&#xff1a;Pre-built.2&#xff0c;pthreads.2&#xff0c;Q…

(三)linux之根文件系統的制作

&#xff08;一&#xff09;準備工作 Ubuntu 16.04系統linux-3.5內核:linux-3.5-20190929交叉編譯工具arm-linux-gcc-4.5.1-v6-vfp-20120301.rarbusybox源碼包&#xff1a;busybox-1.21.1.rar &#xff08;二&#xff09;工具介紹 &#xff08;1&#xff09;交叉編譯器 這個…

c/c++多線程模擬系統資源分配(并通過銀行家算法避免死鎖產生)

銀行家算法數據結構 &#xff08;1&#xff09;可利用資源向量Available 是個含有m個元素的數組&#xff0c;其中的每一個元素代表一類可利用的資源數目。如果Available[j]K&#xff0c;則表示系統中現有Rj類資源K個。 &#xff08;2&#xff09;最大需求矩陣Max 這是一個nm的…

(四)Linux內核模塊化編程

目錄&#xff08;一&#xff09;模塊化編程簡介&#xff08;二&#xff09;安裝卸載模塊命令.&#xff08;三&#xff09;將自定義功能添加到內核三種方法&#xff08;1&#xff09;修改Kconfig和Makefile&#xff08;2&#xff09;直接修改功能對應目錄下的Makefile文件&#…

基于X86平臺的PC機通過網絡發送一個int(32位)整數的字節順序

1.字節順序  字節順序是指占內存多于一個字節類型的數據在內存中的存放順序&#xff0c;通常有小端、大端兩種字節順序。小端字節序指低字節數據存放在內存低地址處&#xff0c;高字節數據存放在內存高地址處&#xff1b;大端字節序是高字節數據存放在低地址處&#xff0c;低字…

Linux內核空間和用戶空間

在Linux系統中存在進程的概念&#xff1a; 進程的分類&#xff1a; 用戶進程&#xff1a;運行在用戶空間的進程被稱為用戶進程 內核進程:運行在內核空間的進程被稱為內核進程 進程的空間&#xff1a; 系統會為每一個進程分0-4G的虛擬尋址空間&#xff0c;在4G的空間中 0-3G&…

codeforces Round #320 (Div. 2) C. A Problem about Polyline(數學) D. Or Game(暴力,數學)

解題思路&#xff1a;就是求數 n 對應的二進制數中有多少個 1 #include <iostream> #include<cstdio> using namespace std; int main(){int n;cin>>n;int ans 0; // while(n){//這也是一種好的方法 // n n&(n-1); // ans; // }while(n…

(五)Linux之設備驅動模型

目錄&#xff08;一&#xff09;Linux內核驅動簡介&#xff08;二&#xff09;雜項設備驅動模型&#xff08;1&#xff09;相關接口&#xff08;2&#xff09;雜項設備注冊過程&#xff08;三&#xff09;早期經典字符設備驅動模型&#xff08;1&#xff09;相關接口&#xff0…

操作系統頁面置換算法(opt,lru,fifo,clock)實現

選擇調出頁面的算法就稱為頁面置換算法。好的頁面置換算法應有較低的頁面更換頻率&#xff0c;也就是說&#xff0c;應將以后不會再訪問或者以后較長時間內不會再訪問的頁面先調出。 常見的置換算法有以下四種&#xff08;以下來自操作系統課本&#xff09;。 1. 最佳置換算法(…

(六)Linux之設備驅動模型(續)

前面我們學習了雜項設備驅動模型、早期經典字符設備驅動模型,這一小節來講解Linux中的標準字符設備驅動。 目錄&#xff08;一&#xff09;為什么引入標準字符設備驅動模型&#xff08;二&#xff09;相關接口&#xff08;三&#xff09;注冊流程&#xff08;四&#xff09;程序…

N個數依次入棧,出棧順序有多少種?

對于每一個數來說&#xff0c;必須進棧一次、出棧一次。我們把進棧設為狀態‘1’&#xff0c;出棧設為狀態‘0’。n個數的所有狀態對應n個1和n個0組成的2n位二進制數。由于等待入棧的操作數按照1‥n的順序排列、入棧的操作數b大于等于出棧的操作數a(a≤b)&#xff0c;因此輸出序…

(七)linux函數接口的使用

前面我們講解了字符設備的驅動模型&#xff0c;有了前面的基礎后&#xff0c;今天學習函數接口就比較容易了 目錄&#xff08;一&#xff09;open函數接口&#xff08;二&#xff09;read函數接口&#xff08;三&#xff09;lseek函數接口&#xff08;四&#xff09;用戶空間和…

(八)linux驅動之ioctl的使用

這篇文章給大家講解一下ioctl的簡單使用&#xff0c;關于ioctl更詳細的教程后面有機會單獨寫出來 &#xff08;一&#xff09;什么是ioctl ioctl是設備驅動程序中對設備的I/O通道進行管理的函數。所謂對I/O通道進行管理&#xff0c;就是對設備的一些特性進行控制&#xff0c;例…

(九)linux中斷編程

目錄&#xff08;一&#xff09;linux中斷的介紹&#xff08;二&#xff09;內核中斷的操作過程&#xff08;三&#xff09;實例代碼&#xff08;一&#xff09;linux中斷的介紹 linux內核中的中斷通過中斷子系統來管理。linux系統中有專門的中斷子系統&#xff0c;原理很復雜…

網絡爬蟲(1)

參考&#xff1a;http://www.cnblogs.com/dongkuo/p/4851735.html算法分析我們現在從需求中提取關鍵詞來逐步分析問題。 首先是“種子節點”。它就是一個或多個在爬蟲程序運行前手動給出的URL&#xff08;網址&#xff09;&#xff0c;爬蟲正是下載并解析這些種子URL指向的頁面…

(十)Linux之等待隊列

&#xff08;一&#xff09;阻塞和非阻塞 阻塞&#xff1a;執行設備操作時&#xff0c;若不能獲得資源&#xff0c;則掛起進程進入休眠直到滿足可操作的條件后再操作。 非阻塞&#xff1a;進程在不能進行設備操作時&#xff0c;并不掛起&#xff0c;它要么放棄&#xff0c;要么…

(十一)linux之poll輪詢

目錄&#xff08;一&#xff09;poll輪詢的作用&#xff08;二&#xff09;poll輪詢相關的接口&#xff08;三&#xff09;poll使用流程&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;poll輪詢的作用 以阻塞的方式打開文件&#xff0c;那么對多個文件讀寫時&a…

校驗碼(海明校驗,CRC冗余校驗,奇偶校驗)

循環冗余校驗碼 CRC碼利用生成多項式為k個數據位產生r個校驗位進行編碼,其編碼長度為nkr所以又稱 (n,k)碼. CRC碼廣泛應用于數據通信領域和磁介質存儲系統中. CRC理論非常復雜,一般書就給個例題,講講方法.現在簡單介紹下它的原理: 在k位信息碼后接r位校驗碼,對于一個給定的(n,k…

(十二)linux內核定時器

目錄&#xff08;一&#xff09;內核定時器介紹&#xff08;二&#xff09;內核定時器相關接口&#xff08;三&#xff09;使用步驟&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;內核定時器介紹 內核定時器并不是用來簡單的定時操作&#xff0c;而是在定時時…

java Proxy(代理機制)

我們知道Spring主要有兩大思想&#xff0c;一個是IoC&#xff0c;另一個就是AOP&#xff0c;對于IoC&#xff0c;依賴注入就不用多說了&#xff0c;而對于Spring的核心AOP來說&#xff0c;我們不但要知道怎么通過AOP來滿足的我們的功能&#xff0c;我們更需要學習的是其底層是怎…