STM32平台控制AS3992 UHF RFID读写模块应用案例

1.1项目说明:

本平台使用STM32做主控,通过串口控制Eleckits UHF RFID读写模块,当红外线感应到物体时,读写器自动执行标签读操作,读写器将识别到的标签ID以Excel的数据格式存储在SD卡中。

总体架构:

3e63b3fbgd95d42d6daeaamp69

垃圾车的机械臂带有红外臂章传感器,当抓取到垃圾桶Spuce 控制RFID读写器读取垃圾桶上的标签信息并处理读到的数据,记录到SD卡中。存入有效的数据后,蜂鸣器报警提示。即完成数据的记录和处理。进而进行下个垃圾桶的垃圾收集。

Spruce和RFID的通信:

3e63b3fbgd95d44cf3e8eamp69

SD卡存储格式:

标号 RFID标签号 日期
1 3005FB63AC1F3841EC880467 2011-8-1-MON-12:00:00
2 3005FB63AC1F3841EC880467 2011-8-1-MON-13:00:00
3 3005FB63AC1F3841EC880467 2011-8-1-MON-14:00:00
4 3005FB63AC1F3841EC880467 2011-8-1-MON-15:00:00

1.2流程图:

3e63b3fbgd95d49ba26d6amp69

1.3实现功能

1.  检测SD卡是否插入,没有插入蜂鸣器报警。需断电后重新插入SD卡。

2.  红外避障功能,当有障碍物时STM32才会通过串口发送命令,节约了耗电量。

3. 显示日期功能,具体到秒。需要在程序中配置时间。

4. 读取有效的标签号存入SD卡中。

5. 创建CSV格式文件,按照上表格式存储数据(会重复记录数据)。可以以表格形式打开,便于查看。

6. 存入有效数据成功后,蜂鸣器报警提示。

1.4外设连接(需参考电路图)

1.  蜂鸣器连接:

正极接STM32 5V引脚。

蜂鸣器另一端接STM32的PB9引脚。

2.       红外避障传感器的连接:

正极接STM32 5V引脚。

负极接STM32 接地引脚。

标有S的引脚接STM32的PE9引脚。

3. RFID连接:

RFID和STM32共地连接。

连接3V电源

STM32的USART2的TX(PA2)连接RFID的RX。

STM32的USART2的RX(PA3)连接RFID的TX。

2.主要程序解读

void SendCmd1(void)
{
cmd_delay();//waiting receive data
USART_SendData(USART2, 0x10);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
USART_SendData(USART2, 0x03);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
USART_SendData(USART2, 0x01);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
}
 
void SendCmd2(void)
{
cmd_delay();//waiting receive data
USART_SendData(USART2, 0x10);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 
}
USART_SendData(USART2, 0x03);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 
}
USART_SendData(USART2, 0x00);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 
}
}
 
void SendCmd3(void)
{
cmd_delay();//waiting receive data
USART_SendData(USART2, 0x43);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 
}
USART_SendData(USART2, 0x04);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
 
}
USART_SendData(USART2, 0x01);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
USART_SendData(USART2, 0xcd);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
}
 
void USART2_IRQHandler(void)
{
//uint8_t RecieveData,i;
if (USART_GetITStatus(USART2, USART_IT_RXNE) != 0)
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);//清除中断标志位
RecieveData = USART_ReceiveData(USART2);
String_to_Hex();//转换成字符
//USART_SendData(USART1, RecieveData);
//while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}
}
}
 
void String_to_Hex(void)//a hex need two string data example: A8 store the file like 'A'and'8'
{
uint8_t value1,value2;
uint8_t Map_value=RecieveData;
 
value1=Map_value/16;//high
if(value1<10)
RecieveData2[count++]=Map_value/16+'0';//high value int to hex
else
RecieveData2[count++]=Map_value/16+'7';//high value int to hex(A,B,C,D,E,F)
 
value2=Map_value;//low
if(value2<10)
RecieveData2[count++]=Map_value+'0';//low value int to hex
else
RecieveData2[count++]=Map_value+'7';//low value int to hex(A,B,C,D,E,F)
}
 
void Write_Mark(void)
{
 
int Mark[5],i;//Mark数组存放标号
 
char name[] = { "Data.csv" };//file name
char Information[]="No.,Tag Num,Date";
f_mount(0, &fs);//挂载逻辑盘符0
res = f_open(&fsrc, name, FA_CREATE_NEW | FA_WRITE);//create file
f_open(&fsrc, name, FA_WRITE);//打开写操作
f_lseek(&fsrc, fsrc.fsize); //文件指针移动到文件底部
if(0==Information_Flag)//说明信息标志位为0时写入说明信息
{
Information_Flag=1;
f_write(&fsrc, &Information, sizeof(Information), &br);//写入说明信息
f_putc('\n',&fsrc);
}
Mark[0] = Mark_Num / 10000+48; //标号计算
Mark[1] = Mark_Num % 10000 / 1000+48;//标号计算
Mark[2] = Mark_Num % 1000 / 100+48;//标号计算
Mark[3] = Mark_Num % 100 / 10+48;//标号计算
Mark[4] = Mark_Num % 10+48;//标号计算
for(i=0;i<5;i++)
{
f_putc(Mark[i], &fsrc);//写入标号
}
f_putc(',',&fsrc);//逗号隔开
 
}
 
void Wtite_SerialNumber(void)
{
char Num[24];//Num数组用来存放24位标签号
memcpy(Num,RecieveData2+20*sizeof(char),24*sizeof(char));//去掉接收到得前20位非标签号,保留24位标签号
f_write(&fsrc,&Num, 24, &br);//写入SD卡中
f_putc(',', &fsrc);//逗号隔开
count=0;//接受到得数据重新开始存储
}
 
void Write_Date(void)
{
count=0;
f_lseek(&fsrc, fsrc.fsize);//移动文件指针
RTC_Get();//获取日期时间
f_write(&fsrc, &cal, sizeof(cal), &br);//写入SD卡中
f_putc(',', &fsrc);//逗号隔开
f_putc('\n', &fsrc);//换行
f_close(&fsrc);//关闭文件
}
 
void Colation(void)
{
 
char b[] = "4405000000";//无效数据
char c[] = "48656C6C6F";//无效数据
char d[] = "494E545643";//无效数据
char f[] = "3033323420";//无效数据
char e[10] = "0";//e数组用来存放接受到得数据
memcpy(e, RecieveData2, 10 * sizeof(char));//拷贝接受到得数据
 
if ((0 == strcmp(b, e)) || (0 == strcmp(c, e)) || (0 == strcmp(d, e))|| (0 == strcmp(f, e)))//和无效数据进行比较
{
C_Flag = 0;//和无效数据相等 C_Flag标志位清零
 
} else
C_Flag = 1;//不相等则置位
count = 0;
}
 
//输入:年份//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{
if(year%4==0) //必须能被4整除
{
if(year0==0)
{
if(year@0==0)return 1;//如果以00结尾,还要能被400整除
else return 0;
}else return 1;
}else return 0;
}
 
u8 RTC_Get_Week(u16 year,u8 month,u8 day)//返回week的下标,0为周一
{//注:1900年1月1日为周1
uint16_t temp2;
uint8_t yearH,yearL;
 
yearH=year/100;
yearL=year0;
// 如果为21世纪,年份数加100
if (yearH>19)
yearL+=100;
// 所过闰年数只算1900年之后的
temp2=yearL+yearL/4;//365/7余数为1,闰年再多加1
 
temp2=temp2%7;
 
temp2=temp2+day+table_week[month-1];
 
if (yearL%4==0&&month<3)//闰年1月或2月,还不必加1,过了2月才要加
temp2--;
return(temp2%7);
}
 
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)//成功返回0,否则返回1
{
 
u16 t;
u32 seccount=0;
if(syear<1970||syear>2099)//从1970-1-1-00:00:00开始记秒
return 1;
 
for(t=1970;t<syear;t++) //把所有年份的秒钟相加
{
if(Is_Leap_Year(t))
 
seccount+=31622400;//闰年的秒钟数
else
seccount+=31536000;//平年的秒钟数
}
 
smon-=1;
 
for(t=0;t<smon;t++) //把前面月份的秒钟数相加
{
seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
 
if(Is_Leap_Year(syear)&&t==1)
 
seccount+=86400;//闰年2月份增加一天的秒钟数
}
seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
 
seccount+=(u32)hour*3600;//小时秒钟数
 
seccount+=(u32)min*60; //分钟秒钟数
 
seccount+=sec;//最后的秒钟加上去
 
//以下为设置时钟
 
PWR_BackupAccessCmd(ENABLE);//区消写保护,使能 RTC 和后备寄存器访问
 
RTC_SetCounter(seccount);//设置RTCCounter的初始值
 
RTC_WaitForSynchro();//等待 RTC 寄存器(RTC_CNT, RTC_ALR and RTC_PRL)与 RTC 的 APB 时钟同步
 
RTC_WaitForLastTask();//等待最近一次对 RTC 寄存器的写操作完成
 
return 0;
}
 
u8 RTC_Get(void)
{
static uint16_t daycnt=0;
uint32_t timecount1=0;
uint32_t temp=0;
uint16_t temp1=0;
int a,b,c;//i,
timecount1=RTC_GetCounter();//获得存储秒数的32位计数器的值
temp=timecount1/86400; //得到天数(秒钟数对应的)
if(daycnt!=temp)//超过一天了
{
daycnt=temp;
temp1= 1970; //仿照linux计时,从1970-1-1-00:00:00开始记秒
while(temp>=365)
{
if(Is_Leap_Year(temp1))//是闰年
{
if(temp>=366)temp-=366;//闰年的秒钟数
else {temp1++;break;}
}
else temp-=365; //平年
temp1++;
}
timer.year=temp1;//得到年份
temp1=0;
while(temp>=28)//超过了一个月
{
if(Is_Leap_Year(timer.year)&&temp1==1)//当年是不是闰年/2月份
{
if(temp>=29)
temp-=29;//闰年的秒钟数
else break;
}
else
{
if(temp>=mon_table[temp1])
temp-=mon_table[temp1];//平年
else break;
}
temp1++;
}
timer.month=temp1+1;//得到月份
timer.day=temp+1; //得到日期
}
temp=timecount1�400; //得到秒钟数
timer.hour=temp/3600; //小时
timer.min=(temp600)/60; //分钟
timer.sec=(temp600)`; //秒钟
timer.week=RTC_Get_Week(timer.year,timer.month,timer.day);//获取星期
cal[0]='2';//Timer.year/1000+48; 数字转换为字符a=a+48;
a=(timer.year-2000)/100;
cal[1]=(timer.year-2000)/100+48;
b=(timer.year-2000-a*100)/10;
cal[2]=(timer.year-2000-a*100)/10+48;
c=(timer.year-2000-a*100-b*10);
cal[3]=(timer.year-2000-a*100-b*10)+48;
//month
cal[4]='-';
a=timer.month/10;
cal[5]=(timer.month/10)+48;
cal[6]=timer.month-a*10+48;
cal[7]='-';
//day
a=timer.day/10;
cal[8]=(timer.day/10)+48;
cal[9]=(timer.day-a*10)+48;
cal[10]='-';
//week,从周日开始记周
switch(timer.week)
{
case 1://
cal[11]=week[0];
cal[12]=week[1];
cal[13]=week[2];
break;
 
case 2://
cal[11]=week[3];
cal[12]=week[4];
cal[13]=week[5];
break;
 
case 3://
cal[11]=week[6];
cal[12]=week[7];
cal[13]=week[8];
break;
case 4://
cal[11]=week[9];
cal[12]=week[10];
cal[13]=week[11];
break;
case 5://
cal[11]=week[12];
cal[12]=week[13];
cal[13]=week[14];
break;
case 6://
cal[11]=week[15];
cal[12]=week[16];
cal[13]=week[17];
break;
case 0://
cal[11]=week[18];
cal[12]=week[19];
cal[13]=week[20];
break;
default:
USART_print("this is a bug");
break;
}
 
cal[14]='-';
//hour
a=timer.hour/10;
cal[15]=(timer.hour/10)+48;
cal[16]=(timer.hour-a*10)+48;
cal[17]=':';
//mini
a=timer.min/10;
cal[18]=(timer.min/10)+48;
cal[19]=(timer.min-a*10)+48;
cal[20]=':';
//sec
a=timer.sec/10;
cal[21]=(timer.sec/10)+48;
cal[22]=(timer.sec-a*10)+48;
 
return 0;
}

完全兼容AMS官方价值RMB 4000元的Roger开发板。适合客户做RFID的二次开发。我们是模块产品,可以通过普通Uart接口把模块集成到您的项目中。我们的价格只是原厂的四分之一!!!!!

Uart串口UHF RFID读写器 915M 无源GEN2超高频读写模块 AS3992

http://item.taobao.com/item.htm?spm=a1z10.1.w4004-3535073336.7.rTV2tL&id=15138367983

RFID 读写器系统包括如下部分:

电源适配器+3.0~3.3V/2A       一个      赠送

RFID 读写模块 一块

RFID 读写天线 (单独选配)

1、3dBi PCB MMCX口 UHF 天线:尺寸 4.5cm*4.1cm

http://item.taobao.com/item.htm?spm=a1z10.5.w4002-3535073328.12.Dejdh5&id=13640879646

2、5dBi PCB MMCX口 UHF 天线:尺寸 10cm * 10cm

http://item.taobao.com/item.htm?spm=a1z10.5.w4002-3535073328.18.Dejdh5&id=23426460127

3、【推荐!!】8dBi 板状定向圆极化 MMCX口 UHF 天线:尺寸 22.5cm*22.5cm

http://item.taobao.com/item.htm?spm=a1z10.5.w4002-3535073328.15.Dejdh5&id=22075632296

与PC 机连接的通信电缆 一条     赠送

EPC UHF GEN2 电子标签 一个    赠送

RFID 读写器开发资料SDK及应用程序    赠送

更多资料、手册,在 http://arm.eleckits.com    下载频道 UHF RFID页面可以直接下载。

您还可以登陆 http://rfid.eleckits.com 下载更多相关资料。

Print Friendly, PDF & Email

发表评论