.\Objects\TEST.axf: Error: L6200E: Symbol fs multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol fileinfo multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol dir multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol FILE_TYPE_TBL multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol file multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol ftemp multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol br multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol bw multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol fatbuf multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol char_upper multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol exf_getfree multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol exfuns_init multiply defined (by exfuns.o and user.o).
.\Objects\TEST.axf: Error: L6200E: Symbol f_typetell multiply defined (by exfuns.o and user.o).
Not enough information to list image symbols.
上面是錯誤信息。
說在exfuns 和 user里面重復定義了。但是沒有在user里面定義,只是包含了exfuns的頭文件這是怎么回事呢?
/*************************************************************************************************/
exfuns.c內容
#include "string.h"
#include "exfuns.h"
#include "fattester.h"
#include "malloc.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////
//FATFS 擴展代碼
//STM32F4工程模板-庫函數版本
//////////////////////////////////////////////////////////////////////////////////
#define FILE_MAX_TYPE_NUM 7 //最多FILE_MAX_TYPE_NUM個大類
#define FILE_MAX_SUBT_NUM 4 //最多FILE_MAX_SUBT_NUM個小類
//文件類型列表
u8*const FILE_TYPE_TBL[FILE_MAX_TYPE_NUM][FILE_MAX_SUBT_NUM]=
{
{"BIN"}, //BIN文件
{"LRC"}, //LRC文件
{"NES"}, //NES文件
{"TXT","C","H"}, //文本文件
{"WAV","MP3","APE","FLAC"},//支持的音樂文件
{"BMP","JPG","JPEG","GIF"},//圖片文件
{"AVI"}, //視頻文件
};
///////////////////////////////公共文件區,使用malloc的時候////////////////////////////////////////////
FATFS *fs[_VOLUMES];//邏輯磁盤工作區.
FIL *file; //文件1
FIL *ftemp; //文件2.
UINT br,bw; //讀寫變量
FILINFO fileinfo; //文件信息
DIR dir; //目錄
u8 *fatbuf; //SD卡數據緩存區
///////////////////////////////////////////////////////////////////////////////////////
//為exfuns申請內存
//返回值:0,成功
//1,失敗
u8 exfuns_init(void)
{
u8 i;
for(i=0;i<_VOLUMES;i++)
{
fs[ i]=(FATFS*)mymalloc(SRAMIN,sizeof(FATFS)); //為磁盤i工作區申請內存
if(!fs[ i])break;
}
file=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //為file申請內存
ftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //為ftemp申請內存
fatbuf=(u8*)mymalloc(SRAMIN,512); //為fatbuf申請內存
if(i==_VOLUMES&&file&&ftemp&&fatbuf)return 0; //申請有一個失敗,即失敗.
else return 1;
}
//將小寫字母轉為大寫字母,如果是數字,則保持不變.
u8 char_upper(u8 c)
{
if(c<'A')return c;//數字,保持不變.
if(c>='a')return c-0x20;//變為大寫.
else return c;//大寫,保持不變
}
//報告文件的類型
//fname:文件名
//返回值:0XFF,表示無法識別的文件類型編號.
// 其他,高四位表示所屬大類,低四位表示所屬小類.
u8 f_typetell(u8 *fname)
{
u8 tbuf[5];
u8 *attr='\0';//后綴名
u8 i=0,j;
while(i<250)
{
i++;
if(*fname=='\0')break;//偏移到了最后了.
fname++;
}
if(i==250)return 0XFF;//錯誤的字符串.
for(i=0;i<5;i++)//得到后綴名
{
fname--;
if(*fname=='.')
{
fname++;
attr=fname;
break;
}
}
strcpy((char *)tbuf,(const char*)attr);//copy
for(i=0;i<4;i++)tbuf[ i]=char_upper(tbuf[ i]);//全部變為大寫
for(i=0;i<FILE_MAX_TYPE_NUM;i++) //大類對比
{
for(j=0;j<FILE_MAX_SUBT_NUM;j++)//子類對比
{
if(*FILE_TYPE_TBL[ i][j]==0)break;//此組已經沒有可對比的成員了.
if(strcmp((const char *)FILE_TYPE_TBL[ i][j],(const char *)tbuf)==0)//找到了
{
return (i<<4)|j;
}
}
}
return 0XFF;//沒找到
}
//得到磁盤剩余容量
//drv:磁盤編號("0:"/"1:")
//total:總容量 (單位KB)
//free:剩余容量 (單位KB)
//返回值:0,正常.其他,錯誤代碼
u8 exf_getfree(u8 *drv,u32 *total,u32 *free)
{
FATFS *fs1;
u8 res;
u32 fre_clust=0, fre_sect=0, tot_sect=0;
//得到磁盤信息及空閑簇數量
res =(u32)f_getfree((const TCHAR*)drv, (DWORD*)&fre_clust, &fs1);
if(res==0)
{
tot_sect=(fs1->n_fatent-2)*fs1->csize; //得到總扇區數
fre_sect=fre_clust*fs1->csize; //得到空閑扇區數
#if _MAX_SS!=512 //扇區大小不是512字節,則轉換為512字節
tot_sect*=fs1->ssize/512;
fre_sect*=fs1->ssize/512;
#endif
*total=tot_sect>>1; //單位為KB
*free=fre_sect>>1; //單位為KB
}
return res;
}
[ i]
[ i][ i][ i][ i][ i][ i]/**********************************************************************************************/
exfuns.h里的內容
[ i]
[ i][ i][ i][ i][ i][ i]
#ifndef _EXFUNS_H
#define _EXFUNS_H
#include <stm32f4xx.h>
#include "ff.h"
//////////////////////////////////////////////////////////////////////////////////
//FATFS 擴展代碼
//STM32F4工程模板-庫函數版本
//淘寶店鋪:http://mcudev.taobao.com
//////////////////////////////////////////////////////////////////////////////////
extern FATFS *fs[_VOLUMES];
extern FIL *file;
extern FIL *ftemp;
extern UINT br,bw;
extern FILINFO fileinfo;
extern DIR dir;
extern u8 *fatbuf;//SD卡數據緩存區
//f_typetell返回的類型定義
//根據表FILE_TYPE_TBL獲得.在exfuns.c里面定義
#define T_BIN 0X00 //bin文件
#define T_LRC 0X10 //lrc文件
#define T_NES 0X20 //nes文件
#define T_TEXT 0X30 //.txt文件
#define T_C 0X31 //.c文件
#define T_H 0X32 //.h文件
#define T_WAV 0X40 //WAV文件
#define T_MP3 0X41 //MP3文件
#define T_APE 0X42 //APE文件
#define T_FLAC 0X43 //FLAC文件
#define T_BMP 0X50 //bmp文件
#define T_JPG 0X51 //jpg文件
#define T_JPEG 0X52 //jpeg文件
#define T_GIF 0X53 //gif文件
#define T_AVI 0X60 //avi文件
u8 exfuns_init(void); //申請內存
u8 f_typetell(u8 *fname); //識別文件類型
u8 exf_getfree(u8 *drv,u32 *total,u32 *free); //得到磁盤總容量和剩余容量
u32 exf_fdsize(u8 *fdname); //得到文件夾大小
#endif
/************************************************************************************************/
user.c里的內容
[ i]
[ i][ i][ i][ i][ i][ i]
#include "exfuns.c"
#include "user.h"
#include "lcd.h"
#include "DS1302.h"
#include "gui.h"
#include "usart.h"
#include "DS18B20.h"
#include "sdio_sdcard.h"
#include "ff.h"
#include "malloc.h"
#include "w25qxx.h"
#include "delay.h"
#include "diskio.h"
/*****************************************************************************
* @name :void lcd_time(int x,int y)
* @date :2020-05-18
* @function :時間顯示函數
* @parameters :int x x方向坐標
int y y方向坐標
* @retvalue :None
******************************************************************************/
void lcd_time(int x,int y)
{ DS1302_GetTime();
// LCD_direction(1);//調整屏方向
LCD_ShowNum2 (x,y,BLUE,WHITE,TimeData .year ,4,16);
Show_Str (x+=32,y,BLUE,YELLOW,"--",32,1);
LCD_Show2Num (x+=16,y,BLUE,WHITE,TimeData .month ,2,16);
Show_Str (x+=16,y,BLUE,WHITE,"--",16,0);
LCD_Show2Num (x+=16,y,BLUE,WHITE,TimeData .day ,2,16);
Show_Str (x+=16,y,BLUE,WHITE," ",16,0);
LCD_Show2Num (x+=8,y,BLUE,WHITE,TimeData .hour ,2,16);
Show_Str (x+=16,y,BLUE,WHITE,":",16,1);
LCD_Show2Num (x+=8,y,BLUE,WHITE,TimeData .minute ,2,16);
Show_Str (x+=16,y,BLUE,YELLOW,":",16,1);
LCD_Show2Num (x+=8,y,BLUE,WHITE,TimeData .second ,2,16);
Show_Str (x+=16,y,BLUE,YELLOW," ",16,1);
LCD_ShowNum2 (x+=8,y,BLUE,WHITE,TimeData .week ,2,16);
}
/*****************************************************************************
* @name :void usart_ds1302(void)
* @date :2020-05-18
* @function :串口調整時間
* @parameters :串口數據發送格式,2020051813140003t以回車結尾
* @retvalue :None
******************************************************************************/
void usart_ds1302()
{ u8 time_buf[8],time_buf1[8];
u8 len, i,t,times;
if(USART_RX_STA&0x8000)//判斷是否有信息發送
{
len=USART_RX_STA&0x3fff;//發送信息的長度
//printf("\r\n你發送的為:\r\n\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//接收串口信息并發回
time_buf[t]=USART_RX_BUF[t];
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
}
//下面為數組分拆合并如0x32,0x30分拆并組合為0x20
for(i=0;i<len/2;)
{
time_buf1[ i]=time_buf[i*2]<<4;//取8位中的低4位,如0x32變為0x20,
time_buf1[ i]=time_buf1[ i]|(time_buf [i*2+1]&0x0f);//將上面取的低4為和這里的低4位合,如0x20和0x01變為0x21
//(time_buf [i*2+1]&0x0f)此公式為將高4位置0,低4位不變,如0x31變為0x01;
USART_SendData(USART1 ,time_buf1[ i]);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
i++;
}
if(time_buf[len-1]==0X74)//如果到數第二位為t則調整時間
DS1302_WriteTime(time_buf1);
USART_RX_STA=0;
}
else
{
times++;
if(times%5000==0)
{
printf("\r\n??STM32??? ????\r\n");
printf("????@ALIENTEK\r\n\r\n");
}
}
delay_ms(800);
}
/*****************************************************************************
* @name :void lcd_ds18b20(int x,int y)
* @date :2020-05-18
* @function :時間顯示函數
* @parameters :int x x方向坐標
int y y方向坐標
* @retvalue :None
******************************************************************************/
void lcd_ds18b20(int x,int y)
{ float go_num=0;
float temp1[2];
DS18B20_Get_Temp(temp1,go_num,1);//取溫度還沒有弄明白
LCD_ShowNumF(x,y,RED,WHITE,temp1[1],temp1[0],3,16);
}
/*****************************************************************************
* @name :void get_sdfree(void)
* @date :2020-05-18
* @function :獲取SD卡容量
* @parameters :None
* @retvalue :None
******************************************************************************/
void get_sdfree()
{
u8 res=0;
u32 total,sdfree;
while(exf_getfree("0",&total,&sdfree)) //得到SD卡的總容量和剩余容量
{
LCD_ShowString(30,150,16,"SD Card Fatfs Error!",0);
printf("sd card fatfs error\r\n");
delay_ms(200);
LCD_Fill(30,150,240,150+16,WHITE); //清除顯示
delay_ms(200);
// LED0=!LED0;//DS0閃爍
}
POINT_COLOR=BLUE;//設置字體為藍色
LCD_ShowString(30,150,16,"FATFS OK!",0);
LCD_ShowString(30,170,16,"SD Total Size: MB",0);
LCD_ShowString(30,190,16,"SD Free Size: MB",0);
printf ("fatfs ok\r\n");
LCD_ShowNum(30+8*14,170,total>>10,5,16); //顯示SD卡總容量 MB
LCD_ShowNum(30+8*14,190,sdfree>>10,5,16); //顯示SD卡剩余容量 MB
printf("sd total size %d MB\r\n",total>>10);
printf("sd free size %d MB\r\n",sdfree>>10);
}
/*****************************************************************************
* @name :void write_sd(int x,int y)
* @date :2020-05-18
* @function :寫數據到SD卡
* @parameters :int x x方向坐標
int y y方向坐標
* @retvalue :None
******************************************************************************/
//BYTE READBUFFER[1024]={0};
void write_sd(u8 first,BYTE *WRITEBUFFER)
{
u8 res;
UINT fnum;
FIL fsrc;//文件對象
FIL fsrcend;
//FATFS fs;
res=f_mount(fs[0],"0:",1); //掛載SD卡
if(first==0)//如果沒有被格式過則將SD卡格式化
{res=f_mkfs("0:",1,4096);//格式化FLASH,1,盤符;1,不需要引導區,8個扇區為1個簇
if(res==0)
{
f_setlabel((const TCHAR *)"0:mcudev"); //設置Flash磁盤的名字為:ALIENTEK
LCD_ShowString(30,150,16,"Flash Disk Format Finish",0); //格式化完成
printf("sd disk format finish\r\n");
}else
{
LCD_ShowString(30,150,16,"Flash Disk Format Error ",0); //格式化失敗
printf("sd disk format error\r\n");
delay_ms(1000);
}
}
res=f_open (&fsrc,"0:/你好.txt",FA_OPEN_EXISTING|FA_WRITE );//創建一個文件,如果存在就打開
if(res==0x00)
{
f_lseek(&fsrc,fsrc.fptr+fsrc.fsize);
f_write(&fsrc, WRITEBUFFER, sizeof(WRITEBUFFER), &fnum);
}
else
{
res=f_open (&fsrc,"0:/你好.txt",FA_CREATE_ALWAYS|FA_WRITE );
if(res==FR_OK)
{ LCD_ShowString (30,210,16,"OPEN WORD OK!",0);
printf("open word ok\r\n");
res=f_write(&fsrc ,WRITEBUFFER ,sizeof(WRITEBUFFER ),&fnum);
if(res==FR_OK)
{
printf("文件寫入成攻,寫入字節數據:%d\r\n",fnum);
printf("寫入的數據為:\r\n%s\r\n",WRITEBUFFER);
LCD_ShowString (30,230,16,WRITEBUFFER,0);
}
}
}
f_close (&fsrc);//關閉文件
f_mount(NULL,"0:",1);//卸載SD卡
}
/*********************************************************************************************************************/
user.h里的內容
#ifndef _USER_H
#define _USER_H
//#include "sys.h"
void lcd_ds1302(int x,int y);
void lcd_ds18b20(int x,int y);
void usart_ds1302(void);
#endif
請大神指教。。。。。
|