STM32+dht11+rc522+jq8400的简单使用

1.dht11的使用

硬件:3v3,gnd,data数据线接一个gpio,三根线即可

软件:

①dht11.c

cs 复制代码
#include "dht11.h"
#include "delay.h"
#include "stdbool.h"
 
static STRUCT_DHT11_TYPEDEF dht11;
 
 
/* 定义DQ端口 可以直接修改该宏定义更改DQ端口引脚定义 */
#define     DHT11_GPIO_RCLK         RCC_APB2Periph_GPIOA
#define     DHT11_GPIO_PORT         GPIOA
#define     DHT11_GPIO_PIN          GPIO_Pin_2
 
#define     DHT11_DQ(x)             GPIO_WriteBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN, (BitAction)x)
#define     DHT11_DQ_STATUS         GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)
 
/**
 * @brief  配置DQ引脚为输入/输出模式
 * @param  out true-输出 false-输入
 * @retval 无
 */
static void dht11_set_inout(bool out)
{
       
	  GPIO_InitTypeDef GPIO_InitStructure;
	  RCC_APB2PeriphClockCmd(DHT11_GPIO_RCLK, ENABLE);     /* 使能端口时钟 */
	
    if(out == true) {
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出 */
    }
    else {
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    /* 上拉输入 */
    }
    GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;       /* 端口配置 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);    /* 初始化IO口 */
}
 
/**
 * @brief  初始化DHT11的引脚
 * @param  无
 * @retval 无
 */
static void dht11_gpio_config(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(DHT11_GPIO_RCLK, ENABLE);    /* 使能端口时钟 */
    
    GPIO_InitStructure.GPIO_Pin   = DHT11_GPIO_PIN;     /* 端口配置 */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;   /* 推挽输出 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);    /* 初始化IO口 */
}
 
/**
 * @brief  初始化DHT11的结构体
 * @param  无
 * @retval 无
 */
static void dht11_struct_config(void)
{
    dht11.temperature = 0.f;
    dht11.temperature_offset = -0.f;
    
    dht11.humidity = 0.f;
    dht11.humidity_offset = -0.f;
}
 
 
/* 功能:向DHT11发送开始信号 */
static void dht11_start(void)
{
    dht11_set_inout(true);  /* 配置为输出模式 */
    DHT11_DQ(0);            /* 拉低DQ引脚 */
    delay_ms(20);           /* 拉低至少18ms */
    DHT11_DQ(1);            /* DQ = 1 */
    delay_us(30);           /* 主机拉高20~40us */
}
 
/*
 * 功能: 等待DHT11的回应
 * 返回值:
 *         返回1:未检测到DHT11的存在
 *         返回0:存在
 */
static unsigned char dht11_waitAck(void)
{   
    unsigned char retry = 0;
    
    dht11_set_inout(false);  /* 配置为输入模式 */
    while(!DHT11_DQ_STATUS && retry < 100) {/* DHT11会拉低80us -- 通知主机传感器正常 */
        retry ++;
        delay_us(1);
    }
    
    if(retry >= 100) return 1;
    else             retry = 0;
    
    while(DHT11_DQ_STATUS && retry < 100) {/* DHT11会拉高80us -- 通知主机准备接收数据 */
        retry ++;
        delay_us(1);
    }
    
    if(retry >= 100)    return 1;
    return 0;
}
 
/*
 * 功能:从DHT11读取一个位
 * 返回值:
 *        1  读取数据为1
 *        0  读取数据为0
 */
static unsigned char dht11_readBit(void)
{
    unsigned char retry = 0;
    
    dht11_set_inout(false);
    while(DHT11_DQ_STATUS && retry < 100) { /* 拉高延时准备输出 -- 等待变为低电平 */
        retry ++;
        delay_us(1);
    }
    
    retry = 0;
    while(!DHT11_DQ_STATUS && retry < 100) {  /* 先拉低50us -- 等待变为高电平 */
        retry ++;
        delay_us(1);
    }
    delay_us(30);   /* 用于判断高电平持续时间,即接收数据为1或0 */
    if(DHT11_DQ_STATUS) return 1;
    return 0;
}
 
/*
 * 功能:从DHT11读取一个字节
 * 返回值:读到的数据
 */
static unsigned char dht11_readByte(void)
{
    unsigned char i,data=0;
    for(i=0;i<8;i++) {
       data <<= 1; 
       data  |= dht11_readBit();
    }
    return data;
}
 
/**
 * @brief  初始化DHT11
 * @param  无
 * @retval 无
 */
void dht11_init(void)
{
    dht11_struct_config();
    dht11_gpio_config();
}
 
/**
 * @brief  DHT11数据采集函数
 * @param  无
 * @retval 无
 * @note   函数执行的基准时间10us
 */
void dht11_measure(void *priv)
{
	  unsigned char i=0;
    unsigned char buf[5];
    dht11_start();
    if( !dht11_waitAck() ) {
        /* 读取数据 数据格式为 湿度整数 + 湿度小数 + 温度整数 + 温度小数 + 校验和(前四位之和) */
        for( i=0;i<5;i++)
            buf[i] = dht11_readByte();
        
        if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) { /* 校验接收到的数据是否正确 */
            dht11.humidity = buf[0] + buf[1] * 0.1f;
            dht11.temperature = buf[2] + buf[3] * 0.1f;
        }
    }
}
 
/**
 * @brief  获取dht11采集的温度数据
 * @param  无
 * @retval 温度数据 0℃-50℃
 */
float dht11_get_temperature(void)
{
    float temperature = dht11.temperature + dht11.temperature_offset;
    if(temperature > 50.f) { temperature = 50.f; }
    if(temperature < 0.f)  { temperature =  0.f; }
    return (temperature);
}
 
/**
 * @brief  获取dht11采集的湿度数据
 * @param  无
 * @retval 湿度数据 20%RH-90%RH
 */
float dht11_get_humidity(void)
{
    float humidity = dht11.humidity + dht11.humidity_offset;
    if(humidity > 90.f) { humidity = 90.f; }
    if(humidity < 20.f) { humidity = 20.f; }
    return (humidity);
}
 
/**
 * @brief  设置dht11的温度补偿值
 * @param  offset - 补偿值
 * @retval 无
 */
void dht11_set_temperature_offset(float offset)
{
    dht11.temperature_offset = offset;
}
 
/**
 * @brief  设置dht11的湿度补偿值
 * @param  offset - 补偿值
 * @retval 无
 */
void dht11_set_humidity_offset(float offset)
{
    dht11.humidity_offset = offset;
}

② dht11.h

cs 复制代码
#ifndef __DHT11_H
#define __DHT11_H
 
#include "stm32f10x.h"
 
typedef struct {
    float temperature;          /* 获取的温度数据 范围:0~50℃ */
    float temperature_offset;   /* 温度补偿值 */
    float humidity;             /* 获取的湿度数据 范围:20%~90% */
    float humidity_offset;      /* 湿度补偿值 */
} STRUCT_DHT11_TYPEDEF;
 
/* ------------------------- DHT11操作函数 ------------------------- */
void        dht11_init                  (void);         /* 初始化DHT11 */
void        dht11_measure               (void *priv);   /* 读取温湿度 */
float       dht11_get_temperature       (void);         /* 获取dht11采集的温度数据 */
float       dht11_get_humidity          (void);         /* 获取dht11采集的湿度数据 */
void        dht11_set_temperature_offset(float offset); /* 设置dht11的温度补偿值 */
void        dht11_set_humidity_offset   (float offset); /* 设置dht11的湿度补偿值 */
 
#endif

③main.c

cs 复制代码
int main(void)
{

  dht11_init();	                  //温湿度传感器初始化
						
	while (1)
	{		
        dht11_measure(NULL);//dht11
		wd = dht11_get_temperature();//获取温度
		sd = dht11_get_humidity();   //获取湿度
		
	    OLED_ShowCHinese(0, 0, 9); 				//温
	    OLED_ShowCHinese(18, 0, 10); 			//度		
		OLED_ShowString(36,0,":",16);           //:
		OLED_ShowNum(48,0,wd,2,16);
		OLED_ShowCHinese(66, 0, 11); 			//℃		
		OLED_ShowCHinese(0, 3, 36); 			//湿
	    OLED_ShowCHinese(18, 3, 10); 			//度		
		OLED_ShowString(36,3,":",16);           //:
		OLED_ShowNum(48,3,sd,2,16);
		OLED_ShowString(70,3,"%",16);           //% 				
	}
}

实现结果如下所示:

2. rc522的使用

硬件:接线定义如下所示,5根线加上3.3v和gnd总共七根线,多出来的一个引脚可不接

软件:

①rc522.c

cs 复制代码
#include "rc522.h"
#include "delay.h"
#include "usart.h"
#include <string.h>
#include "oled.h" 
#include "led.h"
#include "jq8400.h" 

// M1卡分为16个扇区,每个扇区由四个块(块0、块1、块2、块3)组成
// 将16个扇区的64个块按绝对地址编号为:0~63
// 第0个扇区的块0(即绝对地址0块),用于存放厂商代码,已经固化不可更改 
// 每个扇区的块0、块1、块2为数据块,可用于存放数据
// 每个扇区的块3为控制块(绝对地址为:块3、块7、块11.....)包括密码A,存取控制、密码B等
 
/*全局变量*/
unsigned char CT[2];//卡类型
unsigned char SN[4]; //卡号(低字节在前,高字节在后)
unsigned char RFID[16];			//存放RFID 
unsigned char lxl_bit=0;
unsigned char card1_bit=0;
unsigned char card2_bit=0;
unsigned char card3_bit=0;
unsigned char card4_bit=0;
unsigned char total=0;
unsigned char lxl[4]={196,58,104,217};
unsigned char card_1[4]={83,106,11,1};
unsigned char card_2[4]={208,121,31,57};
unsigned char card_3[4]={176,177,143,165};
unsigned char card_4[4]={5,158,10,136};
u8 KEY[6]={0xff,0xff,0xff,0xff,0xff,0xff};
u8 AUDIO_OPEN[6] = {0xAA, 0x07, 0x02, 0x00, 0x09, 0xBC};
unsigned char RFID1[16]={0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};
/*函数声明*/
unsigned char status;
unsigned char s=0x08;
unsigned char ShowON; 
 
#define   RC522_DELAY()  delay_us( 20 )

//ID
char ss[255];
//char data[16];

unsigned char snr, buf[16], TagType[2], SelectedSnr[4], DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 
unsigned char buf1[16];
unsigned char buf2[16];
int a = 1200;
char OK_status;

void RC522_Handel(void)
{	
	u8 num[9];
	u8 i;
//	
    status = PcdRequest(PICC_REQALL,CT);//寻卡
    
//    printf("\r\nstatus>>>>>>%d\r\n", status);
    
    if(status==MI_OK)//寻卡成功
    {			   
		 //printf("\r\n寻卡成功\r\n");
         status=MI_ERR;
         status = PcdAnticoll(SN);//防冲撞
         //这里放你刷完卡想执行的命令	
    }
 

		
}
				 
void RC522_Init ( void )
{
	SPI1_Init();
	
	RC522_Reset_Disable();
	
	RC522_CS_Disable();
    
  PcdReset ();
    
	M500PcdConfigISOType ( 'A' );//设置工作方式
 
}
 
void SPI1_Init(void)	
{
		GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
		
		// CS
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化PB12
    
    // SCK
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // MISO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // RST
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
}
 
 
/*
 * 函数名:SPI_RC522_SendByte
 * 描述  :向RC522发送1 Byte 数据
 * 输入  :byte,要发送的数据
 * 返回  : RC522返回的数据
 * 调用  :内部调用
 */
void SPI_RC522_SendByte ( u8 byte )
{
    u8 counter;
	
    for(counter=0;counter<8;counter++)
    {     
			if ( byte & 0x80 )
					RC522_MOSI_1 ();
			else 
					RC522_MOSI_0 ();
 
//			delay_us ( 3 );
			RC522_DELAY();
		
			RC522_SCK_0 ();
 
//			delay_us ( 1 );
//			delay_us ( 3 );
			RC522_DELAY();
			 
			RC522_SCK_1();
 
//			delay_us ( 3 );
			RC522_DELAY();
			 
			byte <<= 1; 
			
    } 
	
}
 
 
/*
 * 函数名:SPI_RC522_ReadByte
 * 描述  :从RC522发送1 Byte 数据
 * 输入  :无
 * 返回  : RC522返回的数据
 * 调用  :内部调用
 */
u8 SPI_RC522_ReadByte ( void )
{
	u8 counter;
	u8 SPI_Data;
 
 
	for(counter=0;counter<8;counter++)
	{
			SPI_Data <<= 1;
	 
			RC522_SCK_0 ();
 
//			delay_us ( 3 );
		    RC522_DELAY();
		
			if ( RC522_MISO_GET() == 1)
					SPI_Data |= 0x01;
 
//			delay_us ( 2 );
//			delay_us ( 3 );
			RC522_DELAY();
 
			RC522_SCK_1 ();
	
//			delay_us ( 3 );
			RC522_DELAY();
			
	}
	
 
//	printf("****%c****",SPI_Data);
	return SPI_Data;
}
 
 
/*
 * 函数名:ReadRawRC
 * 描述  :读RC522寄存器
 * 输入  :ucAddress,寄存器地址
 * 返回  : 寄存器的当前值
 * 调用  :内部调用
 */
u8 ReadRawRC ( u8 ucAddress )
{
	u8 ucAddr, ucReturn;
	
	
	ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;
	
	RC522_CS_Enable();
	
	SPI_RC522_SendByte ( ucAddr );
	
	ucReturn = SPI_RC522_ReadByte ();
	
	RC522_CS_Disable();
 
	return ucReturn;
}
 
 
/*
 * 函数名:WriteRawRC
 * 描述  :写RC522寄存器
 * 输入  :ucAddress,寄存器地址
 *         ucValue,写入寄存器的值
 * 返回  : 无
 * 调用  :内部调用
 */
void WriteRawRC ( u8 ucAddress, u8 ucValue )
{  
	u8 ucAddr;
 
	ucAddr = ( ucAddress << 1 ) & 0x7E;
	
	RC522_CS_Enable();
	
	SPI_RC522_SendByte ( ucAddr );
	
	SPI_RC522_SendByte ( ucValue );
	
	RC522_CS_Disable();	
}
 
 
/*
 * 函数名:SetBitMask
 * 描述  :对RC522寄存器置位
 * 输入  :ucReg,寄存器地址
 *         ucMask,置位值
 * 返回  : 无
 * 调用  :内部调用
 */
void SetBitMask ( u8 ucReg, u8 ucMask )  
{
    u8 ucTemp;
 
    ucTemp = ReadRawRC ( ucReg );
	
    WriteRawRC ( ucReg, ucTemp | ucMask );    //   set bit mask
 
}
 
 
/*
 * 函数名:ClearBitMask
 * 描述  :对RC522寄存器清位
 * 输入  :ucReg,寄存器地址
 *         ucMask,清位值
 * 返回  : 无
 * 调用  :内部调用
 */
void ClearBitMask ( u8 ucReg, u8 ucMask )  
{
    u8 ucTemp;
 
    ucTemp = ReadRawRC ( ucReg );
	
    WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) );  // clear bit mask
	
	
}
 
 
/*
 * 函数名:PcdAntennaOn
 * 描述  :开启天线 
 * 输入  :无
 * 返回  : 无
 * 调用  :内部调用
 */
void PcdAntennaOn ( void )
{
    u8 uc;
 
    uc = ReadRawRC ( TxControlReg );
	
    if ( ! ( uc & 0x03 ) )
			SetBitMask(TxControlReg, 0x03);
	
}
 
 
/*
 * 函数名:PcdAntennaOff
 * 描述  :开启天线 
 * 输入  :无
 * 返回  : 无
 * 调用  :内部调用
 */
void PcdAntennaOff ( void )
{
 
    ClearBitMask ( TxControlReg, 0x03 );
 
}
 
 
/*
 * 函数名:PcdRese
 * 描述  :复位RC522 
 * 输入  :无
 * 返回  : 无
 * 调用  :外部调用
 */
void PcdReset ( void )
{
    RC522_Reset_Disable();
 
    delay_us ( 1 );
 
    RC522_Reset_Enable();
 
    delay_us ( 1 );
 
    RC522_Reset_Disable();
 
    delay_us ( 1 );
 
    WriteRawRC ( CommandReg, 0x0f );
 
    while ( ReadRawRC ( CommandReg ) & 0x10 );
 
    delay_us ( 1 );
 
    WriteRawRC ( ModeReg, 0x3D );            //定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363
 
    WriteRawRC ( TReloadRegL, 30 );          //16位定时器低位    
    WriteRawRC ( TReloadRegH, 0 );			     //16位定时器高位
 
    WriteRawRC ( TModeReg, 0x8D );				   //定义内部定时器的设置
 
    WriteRawRC ( TPrescalerReg, 0x3E );			 //设置定时器分频系数
 
    WriteRawRC ( TxAutoReg, 0x40 );				   //调制发送信号为100%ASK	
	
 
}
 
 
/*
 * 函数名:M500PcdConfigISOType
 * 描述  :设置RC522的工作方式
 * 输入  :ucType,工作方式
 * 返回  : 无
 * 调用  :外部调用
 */
void M500PcdConfigISOType ( u8 ucType )
{
	if ( ucType == 'A')              //ISO14443_A
  {
		ClearBitMask ( Status2Reg, 0x08 );
		
    WriteRawRC ( ModeReg, 0x3D );  //3F
		
		WriteRawRC ( RxSelReg, 0x86 ); //84
		
		WriteRawRC( RFCfgReg, 0x7F );  //4F
		
		WriteRawRC( TReloadRegL, 30 ); //tmoLength
		
		WriteRawRC ( TReloadRegH, 0 ); //TReloadVal = 'h6a =tmoLength(dec) 
		
		WriteRawRC ( TModeReg, 0x8D );
		
		WriteRawRC ( TPrescalerReg, 0x3E );
		
		delay_us ( 2 );
		
		PcdAntennaOn ( );              //开天线
		
   }
 
}
 
 
/*
 * 函数名:PcdComMF522
 * 描述  :通过RC522和ISO14443卡通讯
 * 输入  :ucCommand,RC522命令字
 *         pInData,通过RC522发送到卡片的数据
 *         ucInLenByte,发送数据的字节长度
 *         pOutData,接收到的卡片返回数据
 *         pOutLenBit,返回数据的位长度
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :内部调用
 */
char PcdComMF522 ( u8 ucCommand, u8 * pInData, u8 ucInLenByte, u8 * pOutData, u32 * pOutLenBit )		
{
    char cStatus = MI_ERR;
    u8 ucIrqEn   = 0x00;
    u8 ucWaitFor = 0x00;
    u8 ucLastBits;
    u8 ucN;
    u32 ul;
 
    switch ( ucCommand )
    {
       case PCD_AUTHENT:		//Mifare认证
          ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEn
          ucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位
          break;
			 
       case PCD_TRANSCEIVE:		//接收发送 发送接收
          ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
          ucWaitFor = 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卡最大等待时间25ms
		
    do 														//认证 与寻卡等待时间	
    {
         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 ParityErr ProtocolErr
		{
			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;   
//			printf(ErrorReg);
    }
   
   SetBitMask ( ControlReg, 0x80 );           // stop timer now
   WriteRawRC ( CommandReg, PCD_IDLE ); 
	
   return cStatus;
 
}
 
 
/*
 * 函数名: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 ( u8 ucReq_code, u8 * pTagType )
{
    char cStatus;  
    u8 ucComMF522Buf [ MAXRLEN ]; 
    u32 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 ( u8 * pSnr )
{
    char cStatus;
    u8 uc, ucSnr_check = 0;
    u8 ucComMF522Buf [ MAXRLEN ]; 
	u32 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 ];			//读出UID
            ucSnr_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 ( u8 * pIndata, u8 ucLen, u8 * pOutData )
{
    u8 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 ( u8 * pSnr )
{
    char ucN;
    u8 uc;
	  u8 ucComMF522Buf [ MAXRLEN ]; 
    u32  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;
	
}
 
 
/*
 * 函数名:PcdAuthState
 * 描述  :验证卡片密码
 * 输入  :ucAuth_mode,密码验证模式
 *                     = 0x60,验证A密钥
 *                     = 0x61,验证B密钥
 *         u8 ucAddr,块地址
 *         pKey,密码
 *         pSnr,卡片序列号,4字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdAuthState ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr )
{
    char cStatus;
	  u8 uc, ucComMF522Buf [ MAXRLEN ];
    u32 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 ) ) )
			
		{
//			if(cStatus != MI_OK)
//					printf("666")	;		
//			else
//				printf("888");
			cStatus = MI_ERR; 
    }
		
    return cStatus;
		
}
 
 
/*
 * 函数名:PcdWrite
 * 描述  :写数据到M1卡一块
 * 输入  :u8 ucAddr,块地址
 *         pData,写入的数据,16字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdWrite ( u8 ucAddr, u8 * pData )
{
    char cStatus;
	  u8 uc, ucComMF522Buf [ MAXRLEN ];
    u32 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卡一块数据
 * 输入  :u8 ucAddr,块地址
 *         pData,读出的数据,16字节
 * 返回  : 状态值
 *         = MI_OK,成功
 * 调用  :外部调用
 */
char PcdRead ( u8 ucAddr, u8 * pData )
{
    char cStatus;
	  u8 uc, ucComMF522Buf [ MAXRLEN ]; 
    u32 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 )
{
    u8 ucComMF522Buf [ MAXRLEN ]; 
    u32  ulLen;
 
    ucComMF522Buf [ 0 ] = PICC_HALT;
    ucComMF522Buf [ 1 ] = 0;
 
    CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
    	PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
 
    return MI_OK;
	
}
 
 
void IC_CMT ( u8 * UID, u8 * KEY, u8 RW, u8 * Dat )
{
    u8 ucArray_ID [ 4 ] = { 0 };//先后存放IC卡的类型和UID(IC卡序列号)
 
    PcdRequest ( 0x52, ucArray_ID );//寻卡
 
    PcdAnticoll ( ucArray_ID );//防冲撞
 
    PcdSelect ( UID );//选定卡
 
    PcdAuthState ( 0x60, 0x10, KEY, UID );//校验
 
    if ( RW )//读写选择,1是读,0是写
        PcdRead ( 0x10, Dat );
 
    else 
        PcdWrite ( 0x10, Dat );
     
    PcdHalt ();	 
	 
}
 
void ShowID(u8 *p)	 //显示卡的卡号,以十六进制显示
{
	u8 num[9];
	u8 i;
 
 	for(i=0;i<4;i++)
	{
		num[i*2]=p[i]/16;
		num[i*2]>9?(num[i*2]+='7'):(num[i*2]+='0');
		num[i*2+1]=p[i]%16;
		num[i*2+1]>9?(num[i*2+1]+='7'):(num[i*2+1]+='0');
	}
	num[8]=0;
	for(i =0;i<10;i++)
		{
		    SN[i] = num[i];
		}
		sprintf(ss,"%s",SN);
 		OLED_ShowString(0,0,"ID:",16);    //oled显示
		OLED_ShowString(18,0,(u8*)ss,16); //oled显示
    GPIO_ResetBits(GPIOA, GPIO_Pin_11);
		delay_ms(5000);
		OLED_Clear();
		GPIO_SetBits(GPIOA,GPIO_Pin_11);
		if(strcmp(SN,"F3355E0D") == 0)
		{
		  //LED0 = 0;
			delay_ms(500);
			//LED0=1;
		}
		else 
		{
			//OLED_ShowString(0,3,"error",16); //oled显示
		}
	

    printf("ID>>>%s\r\n", num);
 
}

②rc522.h

cs 复制代码
#ifndef __RC522_H
#define __RC522_H	
#include "stm32f10x.h"
 

//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                 0
#define 	MI_NOTAGERR           (1)
#define 	MI_ERR                (2)
 
#define	SHAQU1	0X01
#define	KUAI4	0X04
#define	KUAI7	0X07
#define	REGCARD	0xa1
#define	CONSUME	0xa2
#define READCARD	0xa3
#define ADDMONEY	0xa4
 
 
#define SPIReadByte()	SPIWriteByte(0)
u8 SPIWriteByte(u8 byte);
void SPI1_Init(void);
 
#define SET_SPI_CS  (GPIOF->BSRR=0X01)
#define CLR_SPI_CS  (GPIOF->BRR=0X01)
 
 
#define SET_RC522RST  GPIOF->BSRR=0X02
#define CLR_RC522RST  GPIOF->BRR=0X02
 
 
/***********************RC522 函数宏定义**********************/
#define          RC522_CS_Enable()         GPIO_ResetBits ( GPIOA, GPIO_Pin_4 )//A4
#define          RC522_CS_Disable()        GPIO_SetBits ( GPIOA, GPIO_Pin_4 )
 
#define          RC522_Reset_Enable()      GPIO_ResetBits( GPIOA, GPIO_Pin_8 )//A8
#define          RC522_Reset_Disable()     GPIO_SetBits ( GPIOA, GPIO_Pin_8 )
 
#define          RC522_SCK_0()             GPIO_ResetBits( GPIOA, GPIO_Pin_5 )//A5
#define          RC522_SCK_1()             GPIO_SetBits ( GPIOA, GPIO_Pin_5 )
 
#define          RC522_MOSI_0()            GPIO_ResetBits( GPIOA, GPIO_Pin_7 )//A7
#define          RC522_MOSI_1()            GPIO_SetBits ( GPIOA, GPIO_Pin_7 )
 
#define          RC522_MISO_GET()          GPIO_ReadInputDataBit ( GPIOA, GPIO_Pin_6 )//A6
 
void             RC522_Handel               (void);
void             RC522_Init                 ( void );                       //初始化
void             PcdReset                   ( void );                       //复位
void             M500PcdConfigISOType       ( u8 type );                    //工作方式
char             PcdRequest                 ( u8 req_code, u8 * pTagType ); //寻卡
char             PcdAnticoll                ( u8 * pSnr);                   //读卡号
 
char             PcdSelect                  ( u8 * pSnr );
char             PcdAuthState               ( u8 ucAuth_mode, u8 ucAddr, u8 * pKey, u8 * pSnr );
char             PcdWrite                   ( u8 ucAddr, u8 * pData );
char             PcdRead                    ( u8 ucAddr, u8 * pData );

//void ShowID(u16 x,u16 y, u8 *p, u16 charColor, u16 bkColor);	 //显示卡的卡号,以十六进制显示
void ShowID(u8 *p);	 //显示卡的卡号,以十六进制显示

extern unsigned char buf1[16];
extern unsigned char buf2[16]; 
 
#endif

③main.c

cs 复制代码
int main(void)
{
	RC522_Init();      //RFID初始化
						
	while (1)
	{	
			
		RC522_Handel();	
				
	}
}

实现效果:刷一下卡,下面的两个led就亮一会

3.jq8400 的使用

硬件:tx接串口rx,rx接串口tx,5v,gnd,以及接喇叭的正负极,只有接喇叭才能发出语言,我用的是自带flash的jq8400,需要用usb线接电脑,把语言文件存进去,然后才能播放,该模块有专门的上位机以及语言合成软件等资料(上位机用通过tx,rx通过usb转ttl接电脑,usb数据线不行),需要该模块资料的话评论区说一下,该模块最好5v供电,3.3v会有杂音。

软件:

①jq8400.c

cs 复制代码
#include "jq8400.h"   
#include "usart.h"
#include "usart3.h"
 /*
  * @noBug  播放音乐
  */
void playMusic(int i)
{
	switch(i)
	{
		//在任何时候发此命令都会从头开始播放当前曲目
		case 1:	 
		uart3_send_byte(0xAA);
		uart3_send_byte(0x02);
		uart3_send_byte(0x00);
		uart3_send_byte(0xAC);
			break;
		
		//暂停
		case 2:	 
		uart3_send_byte(0xAA);
		uart3_send_byte(0x03);
		uart3_send_byte(0x00);
		uart3_send_byte(0xAD);
			break;
		
		//下一曲
		case 3:	 
		uart3_send_byte(0xAA);
		uart3_send_byte(0x06);
		uart3_send_byte(0x00);
		uart3_send_byte(0xB0);
			break;
		
		//上一曲
		case 4:	 
		uart3_send_byte(0xAA);
		uart3_send_byte(0x05);
		uart3_send_byte(0x00);
		uart3_send_byte(0xAF);
			break;
		
		//音量5:0xAA, 0x13, 0x01, 0x05, 0xC3  //音量10:0xAA, 0x13, 0x01, 0x0A, 0xC8 //音量15:0xAA, 0x13, 0x01, 0x0F, 0xCD
		//音量20:0xAA, 0x13, 0x01, 0x14, 0xD2 //音量25:0xAA, 0x13, 0x01, 0x19, 0xD7 //音量30:0xAA, 0x13, 0x01, 0x1E, 0xDC
		case 5:	 
		uart3_send_byte(0xAA);
		uart3_send_byte(0x13);
		uart3_send_byte(0x01);
		uart3_send_byte(0x0F);
		uart3_send_byte(0xCD);
			break;
		//结束播放
		case 6:
		uart3_send_byte(0xAA);
		uart3_send_byte(0x10);
		uart3_send_byte(0x00);
		uart3_send_byte(0xBA);	
		  break;
		default:
		uart3_send_str((u8 *)"the order does not exist!\r\n");
			break;
	}
}

②jq8400.h

cs 复制代码
#ifndef __JQ8400_H
#define	__JQ8400_H

#include "stm32f10x.h"
#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);
void playMusic(int i);
#endif /* __JQ8400_H */

③main.c

cs 复制代码
int main(void)
{

	usart3_init(9600);	 					  //串口3初始化为9600,jq8400使用
						
	while (1)
	{	
		playMusic(1); //语言播报
		delay_ms(150);	 
		playMusic(5); //设置音量
		delay_ms(1500);	 
	}
}

该模块就不进行演示了,想要完整源码的请一键三连后私聊获取!!!

相关推荐
时空自由民.9 分钟前
无人机系统耗电,低功耗管理问题解决方法(chatgpt)
单片机·嵌入式硬件·无人机
时空自由民.14 分钟前
无人机系统耗电,低功耗管理问题解决方法(腾讯元宝)
单片机·嵌入式硬件·无人机
清风6666661 小时前
基于单片机的双档输出数字直流电压源设计
单片机·mongodb·毕业设计·nosql·课程设计
牛马大师兄2 小时前
STM32独立看门狗IWDG与窗口看门狗WWDG知识梳理笔记
笔记·stm32·单片机·嵌入式硬件·嵌入式·看门狗
夜月yeyue2 小时前
STM32 Flash 访问加速器详解(ART Accelerator)
linux·单片机·嵌入式硬件·uboot·bootloard
A9better2 小时前
嵌入式开发学习日志37——stm32之USART
stm32·嵌入式硬件·学习
国科安芯6 小时前
ASP4644芯片低功耗设计思路解析
网络·单片机·嵌入式硬件·安全
充哥单片机设计6 小时前
【STM32项目开源】基于STM32的智能厨房火灾燃气监控
stm32·单片机·嵌入式硬件
CiLerLinux13 小时前
第四十九章 ESP32S3 WiFi 路由实验
网络·人工智能·单片机·嵌入式硬件
时光の尘13 小时前
【PCB电路设计】常见元器件简介(电阻、电容、电感、二极管、三极管以及场效应管)
单片机·嵌入式硬件·pcb·二极管·电感·三极管·场效应管