痞酷網_PIGOO

 找回密碼
 立即註冊
!!! [系統偵測到廣告阻擋軟體] !!!

如果您覺得痞酷網對您有些許幫助,或者您認同痞酷網的理想,

那麼希望您將痞酷網設定為白名單.

並請在上論壇的時候,動動您的手指,用行動支持我們.

謝謝!
查看: 4478|回復: 14

野人獻曝: STM8S_103 簡易電壓紀錄

[複製鏈接]
發表於 2014-11-13 01:42:36 | 顯示全部樓層 |閱讀模式
本文章最後由 antlu 於 2014-11-13 01:46 AM 編輯

最近持續在玩STM8S 的MCU,先前的太陽能電池控制器仍然有一些小問題,感謝 JOJOLING大的協助,找出了問題,泡沫排序出了問題,這次這個電壓紀錄當初也是因為要抓問題所以慢慢的衍生出來的玩具,其實本來是應該寫到外部的EEPROM,只是,I2C還搞不定,而UART也花了許多時間去摸索(後來發現STM的庫函數有問題),繞了一大圈最終還是用"寄存器方式"解決!!
泡沫排序法當初是想用來過濾雜訊用,沒想到反而造成問題(目前尚無解)若有先進可以幫忙解決,感激不盡!!
元件很簡單很少 STM8S_103 + LCM(1602+74HC595)好像就沒有甚麼零件了!!


/* 20141109  發現 系統提供的 stm8s_uart1.c 有問題無法完成編 譯經過下載網路的檔案之後有改?
但是發生了記憶體溢位的問題,於是改用一般函數來執行
功能: 紀錄模式 每分鐘紀錄一電壓值,並存入EEPROM 總數320個資料(STM8S103 640點)
      紀錄模式時顯示現在的電壓紀錄點
      資料輸出模式: 每按一個鍵紀錄讀出一個值若選擇輸出到PC  則一次輸出320個資料,每按一下輸出一次
      顯示: 讀出紀錄 或 送至PC(完成時顯示OK)
*/

//20131225 THIS CASE FOR 74HC595 DRIVE 8BIT LCM COMMON RS/SER   EN/Latch

//20140928修改給 stm8s103f3 20pin
#include "stm8s.h"
#include "stdio.h"
#include "stm8s_tim1.h"
#include "stm8s_tim4.h"
#include "stm8s_adc1.h"
#include "stm8s_delay.h"
#include "stm8s_flash.h"//20141008
#define LCMPORT GPIOA
#define SER GPIO_PIN_1  //
#define Latch GPIO_PIN_2  //
#define Clk GPIO_PIN_3  //
#define PORT_BEEP GPIOD
#define BEEP1 GPIO_PIN_4
#define DCVoltage ADC1_CHANNEL_4
#define MENU GPIO_PIN_3//MENU PIN
#define ENTER GPIO_PIN_4 //ENTER key
#define MENUPORT GPIOC //c3 menu c4 enter


//@ 變數區
u8 displayword[16];
u16 DataADC;
u8 adc_update_flag;
u16 ADCValue[10];
u8 One_Tenth_Flag;
u8 One_Sec_Flag;
u8 One_Minute_Flag;
u8 One_Hour_Flag;
u8 One_Tenth_Count;//1/10 second
u8 One_Sec_Count;
u8 One_Minute_Count;
u8 count6;
u8 display_time;
u16 Real_Voltagea;
u8 a,b,c,d,e,f,g,h;
u16 databuffer;
u16 wbuffer_count,rbuffer_count,cbuffer_count;


u8 EEPROM_ADDRESS=0xa0;
u16 addr=0x4000;//-------20141008
u8 write_flag;
u8 page_full;
u16 read_out_count;
u16 Volt_From_EPROM;
u8 MENU_flag;
u8 Next_flag;
u16 DS_buffer_count;
u8 ENTER_flag;


//@ 函數區
void Delay_us(u16 ust);
void DelayMs(u16 mst);
void GPIOinit(void);
void Send595(unsigned char Dat);
void LCD_Write_Com(unsigned char com);
void LCD_Write_Data(char Data);
void LCD_Write_Init(char com);
void LCD_Init(void);
void LCD_Clear(void);
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
unsigned int ADC1Set(ADC1_Channel_TypeDef ADC_Channel);
void ADConvert(void);
void DigitalFiltering(void);
void AD_Data_Update(void);
void tim1init(void);
void tim1svc(void);
void tim4init(void);
void tim4svc(void);
void Display_Menu(void);
void TransData(void);
void Get_Volt_32Data(void);
void Store_To_EEPROM(void);
char putchar(char c);//傳送rs232資料出去
void KeyScan(void);



void Delay_us(u16 ust)
{
        while(ust !=0)
        {
                ust--;
        }
}

void DelayMs(u16 mst)
{
        while( mst !=0)
        {
                Delay_us(400);
                mst--;
        }
}

/*
@ define LCM drive pin function
@ define timer4 clock 學習  可以使用 示波器量取波形算出時間
*/
void GPIOinit(void)
{
        GPIO_Init(LCMPORT,SER|Clk|Latch,GPIO_MODE_OUT_PP_HIGH_FAST);//for LCM driver
        GPIO_Init(PORT_BEEP,BEEP1,GPIO_MODE_OUT_PP_HIGH_FAST);//D4
        GPIO_Init(MENUPORT,MENU|ENTER,GPIO_MODE_IN_PU_NO_IT);//變更 sw4 sw5 成為 input
        }

        

//*******************************************
void Send595(unsigned char Dat)
{
         unsigned char i;
         for (i=0;i<8;i++)
         {
          if((Dat & 0x80)!=0)// SER=Dat & 0x80;
                                        {
                                         GPIO_WriteHigh(LCMPORT,SER);
                                  }
                                        else
                                        {
                                        GPIO_WriteLow(LCMPORT,SER);
                                        }
          Dat<<=1;
                                  GPIO_WriteHigh(LCMPORT,Clk);// Clk=1;
                                  GPIO_WriteLow(LCMPORT,Clk);
         }
                                                         
     /*     Latch=1;//20131226 這是關鍵把他取消才能做595後續栓鎖
                                _nop_();
                         Latch=0;
                                _nop_();*/   
}



void LCD_Write_Com(unsigned char com) // 8bit mode  20131225 for 74HC595 8bit mode
{
Send595(com);//送到 74HC595  
GPIO_WriteLow(LCMPORT,SER);;//command mode
GPIO_WriteHigh(LCMPORT,Latch);;
GPIO_WriteLow(LCMPORT,Latch);;
DelayMs(1);
}


void LCD_Write_Data(char Data) // 8bit mode
{
Send595(Data);//送到 74HC595  
GPIO_WriteHigh(LCMPORT,SER);;//Data mode
GPIO_WriteHigh(LCMPORT,Latch);;
GPIO_WriteLow(LCMPORT,Latch);;
DelayMs(1);
}


void LCD_Write_Init(char com) // 8bit mode
{
Send595(com);//送到 74HC595
GPIO_WriteLow(LCMPORT,SER);;//command mode
GPIO_WriteHigh(LCMPORT,Latch);;
GPIO_WriteLow(LCMPORT,Latch);;
DelayMs(1);
}

/*------------------------------------------------
            initial LCM
------------------------------------------------*/
void LCD_Init(void)//20131225 8bit command
{
LCD_Write_Com(0x38); //38 --- 8bit & 2 line ,28 -- 4bit & 2 line
DelayMs(5);
LCD_Write_Com(0x38); //38 --- 8bit & 2 line ,28 -- 4bit & 2 line
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);        
LCD_Write_Com(0x08);    /*显示关闭*/
DelayMs(2);
LCD_Write_Com(0x01);    /*显示清屏*/
DelayMs(2);
LCD_Write_Com(0x06);   /*显示光标移动设置*/  
DelayMs(5);
LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }




/*------------------------------------------------
                LCD_Clear
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
              LCD_Write_String
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
if (y == 0)
{     
LCD_Write_Com(0x80 + x);     
}
else
   {     
    LCD_Write_Com(0xC0 + x);     
    }        
while (*s)
  {     
LCD_Write_Data( *s);     
s ++;     
  }
}
/*------------------------------------------------
              LCD_Write_Char
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{     
if (y == 0)
  {     
   LCD_Write_Com(0x80 + x);     
   }   
else
   {     
    LCD_Write_Com(0xC0 + x);     
    }        
LCD_Write_Data( Data);  
}

/*
@ 輸入變數 ADC_Channel
@ 取10次AD值 ADCValue[ADCcount]
@ 進行排序過濾平均 DATA完整的6次
@ 輸出變數 ADresult
*/
unsigned int ADC1Set(ADC1_Channel_TypeDef ADC_Channel)//讀取不同的AD通道
{
u16 ADresult;
{
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,ADC_Channel,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL0,DISABLE);
ADConvert();
DigitalFiltering();
ADresult=DataADC;
DataADC=0;
adc_update_flag=0;
}
return ADresult;
}

/* @ 進行ADC 10次把資料存在 ADCValue[ADCcount]之中作為過濾使用
   @ 變數 ADCcount
   @ 陣列 ADCValue[ADCcount]
*/
void ADConvert(void)
{
        unsigned char ADCcount =0;
        ADC1->CR1|=0x02;
  ADC1_StartConversion();//ADC開始轉換
        while(ADCcount<10)
        {
                while(ADC1_GetFlagStatus(ADC1_FLAG_EOC)==RESET);
                ADC1_ClearFlag(ADC1_FLAG_AWS0);
                ADCValue[ADCcount]=ADC1_GetConversionValue();
                ADCcount++;
        }
        ADC1->CR1 &= ~0x02;
}

/*
@ 先進行排序把頭尾2個資料去掉如此AD資料就不會亂跳電視會降速度
@ 變數 DataADC
*/
void DigitalFiltering(void)
{
        unsigned char i,j;
        unsigned char cptemp;
/*        
        for(i=10;i>=1;i--)
        {
                for(j=0;j<(i-1);j++)
                {
                        if(ADCValue[j]>ADCValue[j+1])
                        {
                                cptemp=ADCValue[j];
                                ADCValue[j]=ADCValue[j+1];
                                ADCValue[j+1]=cptemp;
                        }
                }
        }
                */
        DataADC=0;

        for(i=2;i<=7;i++)
        {
                DataADC +=ADCValue;
        }
        DataADC /=6;        
}


/*
@把電壓ad port讀入並且換算成電壓值
@ Voltage_AD_count 可以變成參數
@ Real_Voltagea實際換算的電壓
@
*/
void AD_Data_Update(void)
{
        u16 Voltage_AD_count;
         Voltage_AD_count = ADC1Set(DCVoltage);
        Real_Voltagea=(unsigned int)((unsigned long)Voltage_AD_count*3);//1023/1023);//電壓ok 顯示12.0v
//        Real_Voltagea = Voltage_AD_count;
}




/*
@Timer1 2M/20=100khz 除10000次=10hz
@
*/
void tim1init(void)//1秒1計數
{
TIM1_TimeBaseInit(19,TIM1_COUNTERMODE_UP,10000,0);//2M/20=100khz 除10000次=10hz
TIM1_ITConfig(TIM1_IT_UPDATE,ENABLE);
TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);
TIM1_Cmd(ENABLE);
}

/*
@Timer1 2M/20=100khz 除10000次=10hz
@        //-------1/10 秒 作一次的工作 One_Tenth_Flag --> AD轉換
@ //-------1秒 作一次的工作 One_Sec_Flag --> 計秒 PWM 開關
@        //-------1分鐘作一次的工作 One_Minute_Flag --> 倒數計時關 斷MOS_OUTPUT        檢查日落
@        //-------1小時作一次的工作 One_Hour_Flag  --> 計時
@  1/10秒更新一次旗標  adc_update_flag //ADC轉換一次以避免過度忙碌
@
*/
void tim1svc(void)//1/10秒1計數
{
One_Tenth_Flag=1;
One_Tenth_Count++;
if(One_Tenth_Count == 10)
{
//         adc_update_flag=1;//ADC轉換一次以避免過度忙碌
         One_Sec_Flag=1;
         One_Tenth_Count=0;
         One_Sec_Count++;
         if(One_Sec_Count == 60)//----------------60
         {
                 adc_update_flag=1;//一分鐘ADC轉換一次以避免過度忙碌
                 One_Sec_Count=0;
                 One_Minute_Flag=1;
                 One_Minute_Count++;
                 if(One_Minute_Count==60)
                 {
                         One_Minute_Count=0;
                         One_Hour_Flag=1;
                 }
         }
}
        TIM1_ClearFlag(TIM1_FLAG_UPDATE);
}

/*
@Timer4 8bit 計時器先前用於7段掃描顯示
@
*/
void tim4init(void)
{
        TIM4_TimeBaseInit(TIM4_PRESCALER_32,250);//4.05ms
        TIM4_SetCounter(250);
        TIM4_ITConfig(TIM4_IT_UPDATE,ENABLE);//2Mhz/8/250
        TIM4_Cmd(ENABLE);
}

/*
@Timer4 8bit 計時器先前用於7段掃描顯示
@ 更改為 lcm 顯示
@ 輸出波形以確認 計時器的時間
@ 輸出腳位 GPIOD PIN4
*/
void tim4svc(void)
{
display_time++;
if(display_time==20)//10us
{
        
        TransData();//110uS
        Display_Menu();//98.84ms on, 79.56ms off=178ms         
  display_time=0;
  }        
        
  count6++;
if (count6==5)//250>>25
{
        KeyScan();
  count6=0;
  GPIO_WriteReverse(PORT_BEEP,BEEP1);
}

TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
}

/*
@顯示lcm資料 切換旗標  reverse_display_flag
@顯示變數 a b c d e f
*/

void Display_Menu(void)
{        

                                displayword[0]='V';
        displayword[1]='o';
        displayword[2]='l';
        displayword[3]= 't';
        displayword[4]= ':';
        displayword[5]= ' ';
        displayword[6]= a+'0';
        displayword[7]= b+'0';
        displayword[8]= '.';
        displayword[9]= c+'0';
        displayword[10]= d+'0';
                                if(MENU_flag==0)
                                displayword[11]= 'W';
        else
                                displayword[11]= 'R';
        displayword[12]= '-';
        displayword[13]= h+'0';
        displayword[14]= e+'0';
                                displayword[15]= f+'0';

LCD_Write_String(0,1, displayword);
}

void TransData(void)//顯示用的轉換
{
a=Real_Voltagea/1000;
b=(Real_Voltagea%1000)/100;
c=(Real_Voltagea%100)/10;
d=(Real_Voltagea)%10;

h=DS_buffer_count/100;
e=(DS_buffer_count%100)/10;
f=DS_buffer_count%10;
}





void Uart1_Init(void)
{
        //UART1_CR1=0x00;//8bit no parity
  UART1->CR1=0x00;         
        UART1->CR2=0x0c;//enable tx rx
        UART1->CR3=0x20;//2bit stop
        UART1->BRR2=0x00;//baud rate
        UART1->BRR1=0x0d;
}

char putchar(char cc)
{
        UART1->DR=(cc);
        while(UART1->SR&0x80==0);
        delay(160);
        return(cc);
}

/*PC3 MENU-key PC4 ENTER-key call by timer4

*/
void KeyScan(void)//PC3 MENU-key PC4 ENTER-key
{
        if(!GPIO_ReadInputPin(MENUPORT,MENU))//PC3 MENU-key press
        {
        delay(50);
        if(!GPIO_ReadInputPin(MENUPORT,MENU))
        {
                while(!GPIO_ReadInputPin(MENUPORT,MENU));//wait sw release
    MENU_flag++;
                if(MENU_flag>3)
                {
                MENU_flag=0;               
                }
        }        
  }        
        
        
        if(GPIO_ReadInputPin(MENUPORT,ENTER)==0)//PC3 MENU-key press
        {
                delay(50);
                if(!GPIO_ReadInputPin(MENUPORT,ENTER))
                {
                        while(!GPIO_ReadInputPin(MENUPORT,ENTER));//wait sw release
                        ENTER_flag=1;
                }               
  }        
}

void Get_Volt_Data(void)//取代void Get_Volt_32Data(void)一次一個data
{
                 if(adc_update_flag==1)//若放在1分鐘則每分鐘紀錄1次
                   {
                          AD_Data_Update();//940us
                                databuffer=Real_Voltagea;
                                wbuffer_count++;
                                putchar((u8)wbuffer_count);
                                }
                                 write_flag=1;//改成每一秒就寫一次1組資料
}
        



void MENU_0_AD_write (void)//copy form Store_To_EEPROM()
{
        /*write_flag 寫入完成旗標
        databuffer[0] adc存入的資料
        TrData 16bit的 欲寫入資料緩衝
        wbuffer_count 寫入的計數器
        Whigh_Data,Wlow_Data 寫入eprom的緩衝8bit
        
        */
        u16 TrData;
        u8 Whigh_Data,Wlow_Data;        
        FLASH_Unlock(FLASH_MEMTYPE_DATA);
        TrData=databuffer;
        Whigh_Data=(u8)(TrData>>8);
        Wlow_Data=(u8)TrData;
        FLASH_ProgramByte((addr+(wbuffer_count)*2),Whigh_Data);
        FLASH_ProgramByte((addr+(wbuffer_count)*2+1),Wlow_Data);
        if(wbuffer_count>320)
           wbuffer_count=0;
        write_flag=0;//寫入完成
}

void MENU_1_CLR_EPROM (void)
{
        u16 cbuffer_count;
                        for(cbuffer_count=0;cbuffer_count<640;cbuffer_count++)
                {
                        FLASH_EraseByte(addr+(cbuffer_count));
          }
                DS_buffer_count=cbuffer_count;
}

/*
讀取 eeprom的資料copy自 eprom read
Next_Flag 提取下一個data的操作
rbuffer_count 讀取資料的計數值
*/
void MENU_2_READ_EPROM (void)//
{
        u8 rhigh_Data,rlow_Data;
        
if(Next_flag==1)
{
         Next_flag=0;         
rhigh_Data=FLASH_ReadByte(addr+(rbuffer_count)*2);         
rlow_Data=FLASH_ReadByte(addr+(rbuffer_count)*2+1);
         
        Volt_From_EPROM=(u16)rhigh_Data;
        Volt_From_EPROM <<=8;
        Volt_From_EPROM +=(u16) rlow_Data;

        rbuffer_count++;
        if(rbuffer_count>320)
        {
        rbuffer_count=0;
        }
}
}        


void MENU_3_Upload_PC (void)
{//read byte
                u8 high_Data,low_Data;               
        //        int *dataEprom;
                for(rbuffer_count=0;rbuffer_count<320;rbuffer_count++)
                {
                                high_Data=FLASH_ReadByte(addr+(rbuffer_count)*2);         
                                low_Data=FLASH_ReadByte(addr+(rbuffer_count)*2+1);
                        putchar(high_Data);//
                        putchar(low_Data);//
                        DS_buffer_count=rbuffer_count;
          }        
}


        
void main(void)
{
        u8 da=0;
        GPIOinit();//顯示用
        tim1init();        
        tim4init();
        rim();        
        GPIO_WriteLow(LCMPORT,Latch);;
        GPIO_WriteLow(LCMPORT,SER);;
        DelayMs(100);
        LCD_Init();
        LCD_Clear();
        Uart1_Init();

while(1)
{
  switch(MENU_flag)//顯示用
        {               
                case 0: LCD_Write_String(0,0, "Write Data EPROM");  //顯示紀錄data
                        if(ENTER_flag)
                                                {
                                                        wbuffer_count=0;
                                                        ENTER_flag=0;
                                                }
                                                Get_Volt_Data();//紀錄data
                                                MENU_0_AD_write ();
                                                Real_Voltagea= databuffer; //顯示目前電壓值
                                                DS_buffer_count= wbuffer_count; //顯示目前寫入位址

                                                break;
                case 1:        LCD_Write_String(0,0, "CLEAR EPROM DATA "); //清除紀錄data
                        wbuffer_count=0;
                        if(ENTER_flag)
                                                {
                                                        MENU_1_CLR_EPROM ();
                                                        ENTER_flag=0;
                                                }               
                                                DS_buffer_count=cbuffer_count;
                        break;        
                case 2: LCD_Write_String(0,0, "READ EPROM DATA ");
                        if(ENTER_flag)
                                                {
                                                        Next_flag=1;
                                                        MENU_2_READ_EPROM();
                                                        ENTER_flag=0;
                                                        putchar((u8)rbuffer_count);
                                                }        
                                                Real_Voltagea= Volt_From_EPROM;
                                                DS_buffer_count=rbuffer_count;
                                                
               
                                                //紀錄讀出               
               
                                                break;
                case 3CD_Write_String(0,0, " UPLOAD to PC   ");//data 上傳pc
                        if(ENTER_flag)
                                                {
                                                        MENU_3_Upload_PC ();
                                                        ENTER_flag=0;
                                                }        
                                                DS_buffer_count=rbuffer_count;                                                
                                          break;

                default:break;               
        }
}
}

@far @interrupt void TIM1_OVF_IRQ(void)
{
        tim1svc();
}

@far @interrupt void TIM4_OVF_IRQ(void)
{
        tim4svc();
}




#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


評分

7

查看全部評分

發表於 2014-11-13 06:51:21 | 顯示全部樓層
紀錄模式 每分鐘紀錄一電壓值,並存入EEPROM 總數320個資料
EEPROM 不是有次數限制嗎? 以100000次來算好像2個多月就會掛掉~~~不知道我的理解對嗎?
發表於 2014-11-13 08:34:30 | 顯示全部樓層

看到你的那個常式 void DigitalFiltering(void)

給你看看這個, 好像很有用的, 類似移動平均法, 也是一階系統的, 等於電容濾波, 很強的數字能力, 速度快, 占用RAM少
http://xiaolabadiy.tumblr.com/po ... e-low-pass-filter-c
發表於 2014-11-13 11:10:56 | 顯示全部樓層
本文章最後由 jojoling 於 2014-11-13 11:19 AM 編輯

做Filter 有問題

for(i=2;i<=7;i++)
{
         DataADC +=ADCValue;
}

應該為:

[code]for(i=2;i<=7;i++)
{
       DataADC +=ADCValue [ i ];
}

另外,那個排序看起來是正確的~
i =10 ~ j 動作為 0-8~ 所以資料邊界交換為 ADCValue[0]到  ADCValue[9]
i=2~ j loop 為 0到1
i=1 ~ j loop 不會動作




發表於 2014-11-13 15:55:22 | 顯示全部樓層
看到其他大大的回應...
這裏也提供一個簡單的想法...

/*
@ 先進行排序把頭尾2個資料去掉如此AD資料就不會亂跳電視會降速度
@ 變數 DataADC
@
@ 這個跟奧運評分類似...去除最高與最低(各一位或各兩位)...
@ 這裏有一個簡單的想法,就是設Max跟Min...
@ 全部總和 DataADC - ADCmax - ADC-min 就是去除最高與最低
@ 這樣一個for迴圈,就可以取得ADC總和,Max,Min...(可以節省運算時間..)

*/
// 10值去除 最高與最低...剩8個
void DigitalFiltering(void)
{
        u16 ADCmax,ADCmin;
        unsigned char cnt=0;

        // 10個值去除 最高與最低各1個,剩8個
        DataADC = ADCmax = ADCmin = ADCValue[0];
        for(cnt=1; cnt<=9; cnt++)
        {
             DataADC += ADCValue[cnt];
             if(ADCmax <ADCValue[cnt]) ADCmax = ADCValue[cnt] ;
             if(ADCmin >ADCValue[cnt]) ADCmin = ADCValue[cnt] ;

        }
        // 10值去除 最高與最低...剩8個
        DataADC =(DataADC - ADCmax - ADC-min)/8;        
}


//10個值,去除 最高與最低各2個,剩6個
void DigitalFiltering(void)
{
        u16 ADCmax,  ADCmin;
        u16 ADCmax1, ADCmin1;
        unsigned char cnt=0;

        ADCmax1 = ADCmax = ADC_LOW;   //最小值 應該是0
        ADCmin1 = ADCmin = ADC_HIGH;  //最大值 應該是65535

        for(cnt=0; cnt<=9; cnt++)
        {
             DataADC +=   ADCValue[cnt];
             if(ADCmax  < ADCValue[cnt]) ADCmax = ADCValue[cnt];
             if(ADCmax1 < ADCmax ){ ADCmax = ADCmax1; ADCmax1 = ADCValue[cnt]}
             if(ADCmin >ADCValue[cnt]) ADCmin = ADCValue[cnt] ;
             if(ADCmin1 > ADCmin ){ ADCmin = ADCmin1; ADCmin1 = ADCValue[cnt]}
        }
        //10個值,去除 最高與最低各2個,剩6個
        DataADC =(DataADC - ADCmax1 -ADCmax - ADCmin1 - ADCmin)/6;        
}





補充內容 (2014-11-13 06:07 PM):
//10個值,去除 最高與最低各2個,剩6個
// 一開始(for迴圈之前)要 清除 DataADC 值
DataADC = 0
 樓主| 發表於 2014-11-13 22:21:10 | 顯示全部樓層

拍寫啦(不好意思啦!) 昨天想說把草稿寫一寫 因為讀卡機當掉了,照片取不出來,版規要求一定要照片,所以就把它暫存起來,沒想到陰錯陽差就出去了!(WISH大請見諒我不是故意的!) 今天早上發現泡沫排序沒問題,問題在我的筆誤(抄人家的程式也會筆誤)而且誤了兩個,一個是"=" 誤成"-" 另外一個是 人家是8BIT 我的是16BIT 就這樣啦!!

DSC08085.JPG

DSC08086.JPG

DSC08087.JPG
  1. /*20141113 無法使用 printf 指令會造成 overflow
  2. 20141113 發現泡沫排序的緩衝值應該使用16bit
  3. 20141109  發現 系統提供的 stm8s_uart1.c 有問題無法完成編 譯經過下載網路的檔案之後有改?
  4. 但是發生了記憶體溢位的問題,於是改用一般函數來執行

  5. 功能: 紀錄模式 每分鐘紀錄一電壓值,並存入EEPROM 總數320個資料(STM8S103 640點)
  6.       紀錄模式時顯示現在的電壓紀錄點
  7.                         資料輸出模式: 每按一個鍵紀錄讀出一個值若選擇輸出到PC  則一次輸出320個資料,每按一下輸出一次
  8.                         顯示: 讀出紀錄 或 送至PC(完成時顯示OK)

  9. */

  10. //20131225 THIS CASE FOR 74HC595 DRIVE 8BIT LCM COMMON RS/SER   EN/Latch

  11. //20140928修改給 stm8s103f3 20pin
  12. #include "stm8s.h"
  13. #include "stdio.h"
  14. #include "stm8s_tim1.h"
  15. #include "stm8s_tim4.h"
  16. #include "stm8s_adc1.h"
  17. #include "stm8s_delay.h"
  18. #include "stm8s_flash.h"//20141008
  19. #define LCMPORT GPIOA
  20. #define SER GPIO_PIN_1  //
  21. #define Latch GPIO_PIN_2  //
  22. #define Clk GPIO_PIN_3  //
  23. #define PORT_BEEP GPIOD
  24. #define BEEP1 GPIO_PIN_4
  25. #define DCVoltage ADC1_CHANNEL_4
  26. #define MENU GPIO_PIN_3//MENU PIN
  27. #define ENTER GPIO_PIN_4 //ENTER key
  28. #define MENUPORT GPIOC //c3 menu c4 enter


  29. //@ 變數區
  30. u8 displayword[16];
  31. u16 DataADC;
  32. u8 adc_update_flag;
  33. u16 ADCValue[10];
  34. u8 One_Tenth_Flag;
  35. u8 One_Sec_Flag;
  36. u8 One_Minute_Flag;
  37. u8 One_Hour_Flag;
  38. u8 One_Tenth_Count;//1/10 second
  39. u8 One_Sec_Count;
  40. u8 One_Minute_Count;
  41. u8 count6;
  42. u8 display_time;
  43. u16 Real_Voltagea;
  44. u8 a,b,c,d,e,f,g,h;
  45. u16 databuffer;
  46. u16 wbuffer_count,rbuffer_count,cbuffer_count;


  47. u8 EEPROM_ADDRESS=0xa0;
  48. u16 addr=0x4000;//-------20141008
  49. u8 write_flag;
  50. u8 page_full;
  51. u16 read_out_count;
  52. u16 Volt_From_EPROM;
  53. u8 MENU_flag;
  54. u8 Next_flag;
  55. u16 DS_buffer_count;
  56. u8 ENTER_flag;
  57. u8 ans;

  58. //@ 函數區
  59. void Delay_us(u16 ust);
  60. void DelayMs(u16 mst);
  61. void GPIOinit(void);
  62. void Send595(unsigned char Dat);
  63. void LCD_Write_Com(unsigned char com);
  64. void LCD_Write_Data(char Data);
  65. void LCD_Write_Init(char com);
  66. void LCD_Init(void);
  67. void LCD_Clear(void);
  68. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
  69. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
  70. unsigned int ADC1Set(ADC1_Channel_TypeDef ADC_Channel);
  71. void ADConvert(void);
  72. void DigitalFiltering(void);
  73. void AD_Data_Update(void);
  74. void tim1init(void);
  75. void tim1svc(void);
  76. void tim4init(void);
  77. void tim4svc(void);
  78. void Display_Menu(void);
  79. void TransData(void);
  80. void Get_Volt_32Data(void);
  81. void Store_To_EEPROM(void);
  82. char putchar(char c);//傳送rs232資料出去
  83. void KeyScan(void);



  84. void Delay_us(u16 ust)
  85. {
  86.         while(ust !=0)
  87.         {
  88.                 ust--;
  89.         }
  90. }

  91. void DelayMs(u16 mst)
  92. {
  93.         while( mst !=0)
  94.         {
  95.                 Delay_us(400);
  96.                 mst--;
  97.         }
  98. }

  99. /*
  100. @ define LCM drive pin function
  101. @ define timer4 clock 學習  可以使用 示波器量取波形算出時間
  102. */
  103. void GPIOinit(void)
  104. {
  105.         GPIO_Init(LCMPORT,SER|Clk|Latch,GPIO_MODE_OUT_PP_HIGH_FAST);//for LCM driver
  106.         GPIO_Init(PORT_BEEP,BEEP1,GPIO_MODE_OUT_PP_HIGH_FAST);//D4
  107.         GPIO_Init(MENUPORT,MENU|ENTER,GPIO_MODE_IN_PU_NO_IT);//變更 sw4 sw5 成為 input
  108.         }

  109.        

  110. //*******************************************
  111. void Send595(unsigned char Dat)
  112. {
  113.          unsigned char i;
  114.          for (i=0;i<8;i++)
  115.          {
  116.           if((Dat & 0x80)!=0)// SER=Dat & 0x80;
  117.                                         {
  118.                                          GPIO_WriteHigh(LCMPORT,SER);
  119.                                   }
  120.                                         else
  121.                                         {
  122.                                         GPIO_WriteLow(LCMPORT,SER);
  123.                                         }
  124.           Dat<<=1;
  125.                                   GPIO_WriteHigh(LCMPORT,Clk);// Clk=1;
  126.                                   GPIO_WriteLow(LCMPORT,Clk);
  127.          }
  128.                                                          
  129.      /*     Latch=1;//20131226 這是關鍵把他取消才能做595後續栓鎖
  130.                                 _nop_();
  131.                          Latch=0;
  132.                                 _nop_();*/   
  133. }



  134. void LCD_Write_Com(unsigned char com) // 8bit mode  20131225 for 74HC595 8bit mode
  135. {
  136. Send595(com);//送到 74HC595  
  137. GPIO_WriteLow(LCMPORT,SER);;//command mode
  138. GPIO_WriteHigh(LCMPORT,Latch);;
  139. GPIO_WriteLow(LCMPORT,Latch);;
  140. DelayMs(1);
  141. }


  142. void LCD_Write_Data(char Data) // 8bit mode
  143. {
  144. Send595(Data);//送到 74HC595  
  145. GPIO_WriteHigh(LCMPORT,SER);;//Data mode
  146. GPIO_WriteHigh(LCMPORT,Latch);;
  147. GPIO_WriteLow(LCMPORT,Latch);;
  148. DelayMs(1);
  149. }


  150. void LCD_Write_Init(char com) // 8bit mode
  151. {
  152. Send595(com);//送到 74HC595
  153. GPIO_WriteLow(LCMPORT,SER);;//command mode
  154. GPIO_WriteHigh(LCMPORT,Latch);;
  155. GPIO_WriteLow(LCMPORT,Latch);;
  156. DelayMs(1);
  157. }

  158. /*------------------------------------------------
  159.             initial LCM
  160. ------------------------------------------------*/
  161. void LCD_Init(void)//20131225 8bit command
  162. {
  163. LCD_Write_Com(0x38); //38 --- 8bit & 2 line ,28 -- 4bit & 2 line
  164. DelayMs(5);
  165. LCD_Write_Com(0x38); //38 --- 8bit & 2 line ,28 -- 4bit & 2 line
  166. DelayMs(5);
  167. LCD_Write_Com(0x38);
  168. DelayMs(5);       
  169. LCD_Write_Com(0x08);    /*显示关闭*/
  170. DelayMs(2);
  171. LCD_Write_Com(0x01);    /*显示清屏*/
  172. DelayMs(2);
  173. LCD_Write_Com(0x06);   /*显示光标移动设置*/  
  174. DelayMs(5);
  175. LCD_Write_Com(0x0C);    /*显示开及光标设置*/
  176.    }




  177. /*------------------------------------------------
  178.                 LCD_Clear
  179. ------------------------------------------------*/
  180. void LCD_Clear(void)
  181. {
  182. LCD_Write_Com(0x01);
  183. DelayMs(5);
  184. }
  185. /*------------------------------------------------
  186.               LCD_Write_String
  187. ------------------------------------------------*/
  188. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
  189. {     
  190. if (y == 0)
  191. {     
  192. LCD_Write_Com(0x80 + x);     
  193. }
  194. else
  195.    {     
  196.     LCD_Write_Com(0xC0 + x);     
  197.     }        
  198. while (*s)
  199.   {     
  200. LCD_Write_Data( *s);     
  201. s ++;     
  202.   }
  203. }
  204. /*------------------------------------------------
  205.               LCD_Write_Char
  206. ------------------------------------------------*/
  207. void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
  208. {     
  209. if (y == 0)
  210.   {     
  211.    LCD_Write_Com(0x80 + x);     
  212.    }   
  213. else
  214.    {     
  215.     LCD_Write_Com(0xC0 + x);     
  216.     }        
  217. LCD_Write_Data( Data);  
  218. }

  219. /*
  220. @ 輸入變數 ADC_Channel
  221. @ 取10次AD值 ADCValue[ADCcount]
  222. @ 進行排序過濾平均 DATA完整的6次
  223. @ 輸出變數 ADresult
  224. */
  225. unsigned int ADC1Set(ADC1_Channel_TypeDef ADC_Channel)//讀取不同的AD通道
  226. {
  227. u16 ADresult;
  228. {
  229. ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,ADC_Channel,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL0,DISABLE);
  230. ADConvert();
  231. DigitalFiltering();
  232. ADresult=DataADC;
  233. DataADC=0;
  234. adc_update_flag=0;
  235. }
  236. return ADresult;
  237. }

  238. /* @ 進行ADC 10次把資料存在 ADCValue[ADCcount]之中作為過濾使用
  239.    @ 變數 ADCcount
  240.    @ 陣列 ADCValue[ADCcount]
  241. */
  242. void ADConvert(void)
  243. {
  244.         unsigned char ADCcount =0;
  245.         ADC1->CR1|=0x02;
  246.   ADC1_StartConversion();//ADC開始轉換
  247.         while(ADCcount<10)
  248.         {
  249.                 while(ADC1_GetFlagStatus(ADC1_FLAG_EOC)==RESET);
  250.                 ADC1_ClearFlag(ADC1_FLAG_AWS0);
  251.                 ADCValue[ADCcount]=ADC1_GetConversionValue();
  252.                 ADCcount++;
  253.         }
  254.         ADC1->CR1 &= ~0x02;
  255. }

  256. /*
  257. @ 先進行排序把頭尾2個資料去掉如此AD資料就不會亂跳電視會降速度
  258. @ 變數 DataADC
  259. */
  260. void DigitalFiltering(void)
  261. {
  262.         unsigned char i,j;
  263.         unsigned int cptemp;
  264.        
  265.         for(i=10;i>=1;i--)
  266.         {
  267.                 for(j=0;j<(i-1);j++)
  268.                 {
  269.                         if(ADCValue[j]>ADCValue[j+1])
  270.                         {
  271.                                 cptemp=ADCValue[j];
  272.                                 ADCValue[j]=ADCValue[j+1];
  273.                                 ADCValue[j+1]=cptemp;
  274.                         }
  275.                 }
  276.         }
  277.                
  278.         DataADC=0;

  279.         for(i=2;i<=7;i++)
  280.         {
  281.                 DataADC +=ADCValue[i];
  282.         }
  283.         DataADC /=6;       
  284. }


  285. /*
  286. @把電壓ad port讀入並且換算成電壓值
  287. @ Voltage_AD_count 可以變成參數
  288. @ Real_Voltagea實際換算的電壓
  289. @
  290. */
  291. void AD_Data_Update(void)
  292. {
  293.         u16 Voltage_AD_count;
  294.          Voltage_AD_count = ADC1Set(DCVoltage);
  295.         Real_Voltagea=(unsigned int)((unsigned long)Voltage_AD_count*3);//1023/1023);//電壓ok 顯示12.0v
  296. //        Real_Voltagea = Voltage_AD_count;
  297. }




  298. /*
  299. @Timer1 2M/20=100khz 除10000次=10hz
  300. @
  301. */
  302. void tim1init(void)//1秒1計數
  303. {
  304. TIM1_TimeBaseInit(19,TIM1_COUNTERMODE_UP,10000,0);//2M/20=100khz 除10000次=10hz
  305. TIM1_ITConfig(TIM1_IT_UPDATE,ENABLE);
  306. TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);
  307. TIM1_Cmd(ENABLE);
  308. }

  309. /*
  310. @Timer1 2M/20=100khz 除10000次=10hz
  311. @        //-------1/10 秒 作一次的工作 One_Tenth_Flag --> AD轉換
  312. @ //-------1秒 作一次的工作 One_Sec_Flag --> 計秒 PWM 開關
  313. @        //-------1分鐘作一次的工作 One_Minute_Flag --> 倒數計時關 斷MOS_OUTPUT        檢查日落
  314. @        //-------1小時作一次的工作 One_Hour_Flag  --> 計時
  315. @  1/10秒更新一次旗標  adc_update_flag //ADC轉換一次以避免過度忙碌
  316. @
  317. */
  318. void tim1svc(void)//1/10秒1計數
  319. {
  320. One_Tenth_Flag=1;
  321. One_Tenth_Count++;
  322. if(One_Tenth_Count == 10)
  323. {
  324.          adc_update_flag=1;//ADC轉換一次以避免過度忙碌
  325.          One_Sec_Flag=1;
  326.          One_Tenth_Count=0;
  327.          One_Sec_Count++;
  328.          if(One_Sec_Count == 60)//----------------60
  329.          {
  330.         //         adc_update_flag=1;//一分鐘ADC轉換一次以避免過度忙碌
  331.                  One_Sec_Count=0;
  332.                  One_Minute_Flag=1;
  333.                  One_Minute_Count++;
  334.                  if(One_Minute_Count==60)
  335.                  {
  336.                          One_Minute_Count=0;
  337.                          One_Hour_Flag=1;
  338.                  }
  339.          }
  340. }
  341.         TIM1_ClearFlag(TIM1_FLAG_UPDATE);
  342. }

  343. /*
  344. @Timer4 8bit 計時器先前用於7段掃描顯示
  345. @
  346. */
  347. void tim4init(void)
  348. {
  349.         TIM4_TimeBaseInit(TIM4_PRESCALER_32,250);//4.05ms
  350.         TIM4_SetCounter(250);
  351.         TIM4_ITConfig(TIM4_IT_UPDATE,ENABLE);//2Mhz/8/250
  352.         TIM4_Cmd(ENABLE);
  353. }

  354. /*
  355. @Timer4 8bit 計時器先前用於7段掃描顯示
  356. @ 更改為 lcm 顯示
  357. @ 輸出波形以確認 計時器的時間
  358. @ 輸出腳位 GPIOD PIN4
  359. */
  360. void tim4svc(void)
  361. {
  362. display_time++;
  363. if(display_time==20)//10us
  364. {
  365.        
  366.         TransData();//110uS
  367.         Display_Menu();//98.84ms on, 79.56ms off=178ms        
  368.   display_time=0;
  369.   }       
  370.        
  371.   count6++;
  372. if (count6==5)//250>>25
  373. {
  374.         KeyScan();
  375.   count6=0;
  376.   GPIO_WriteReverse(PORT_BEEP,BEEP1);
  377. }

  378. TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
  379. }

  380. /*
  381. @顯示lcm資料 切換旗標  reverse_display_flag
  382. @顯示變數 a b c d e f
  383. */

  384. void Display_Menu(void)
  385. {       

  386.                                 displayword[0]='V';
  387.         displayword[1]='o';
  388.         displayword[2]='l';
  389.         displayword[3]= 't';
  390.         displayword[4]= ':';
  391.         displayword[5]= ' ';
  392.         displayword[6]= a+'0';
  393.         displayword[7]= b+'0';
  394.         displayword[8]= '.';
  395.         displayword[9]= c+'0';
  396.         displayword[10]= d+'0';
  397.                                 if(MENU_flag==0)
  398.                                 displayword[11]= 'W';
  399.         else
  400.                                 displayword[11]= 'R';
  401.         displayword[12]= '-';
  402.         displayword[13]= h+'0';
  403.         displayword[14]= e+'0';
  404.                                 displayword[15]= f+'0';

  405. LCD_Write_String(0,1, displayword);
  406. }

  407. void TransData(void)//顯示用的轉換
  408. {
  409. a=Real_Voltagea/1000;
  410. b=(Real_Voltagea%1000)/100;
  411. c=(Real_Voltagea%100)/10;
  412. d=(Real_Voltagea)%10;

  413. h=DS_buffer_count/100;
  414. e=(DS_buffer_count%100)/10;
  415. f=DS_buffer_count%10;
  416. }





  417. void Uart1_Init(void)
  418. {
  419.         //UART1_CR1=0x00;//8bit no parity
  420.   UART1->CR1=0x00;        
  421.         UART1->CR2=0x0c;//enable tx rx
  422.         UART1->CR3=0x20;//2bit stop
  423.         UART1->BRR2=0x00;//baud rate
  424.         UART1->BRR1=0x0d;
  425. }

  426. char putchar(char cc)//傳送資料給pc
  427. {
  428.         UART1->DR=(cc);
  429.         while(UART1->SR&0x80==0);
  430.         delay(200);
  431.         return(cc);
  432. }

  433. char getchar(void)//接收pc資料
  434. {
  435.         char c;
  436.         while((UART1->SR&0x20)==0);
  437.                 delay(200);
  438.         return(UART1->DR);
  439. }

  440. /*------------------------------------------------
  441.                     发送一个字符串
  442. ------------------------------------------------*/
  443. void PutString(unsigned char *s)
  444. {
  445. while(*s!='\0')// \0 表示字符串结束标志,
  446.                 //通过检测是否字符串末尾
  447.   {
  448.   putchar(*s);
  449.   s++;
  450.   }
  451. }
  452. /*
  453. PutString("UART test,技术论坛:www.doflye.net thank you!");


  454. */



  455. /*PC3 MENU-key PC4 ENTER-key call by timer4

  456. */
  457. void KeyScan(void)//PC3 MENU-key PC4 ENTER-key
  458. {
  459.         if(!GPIO_ReadInputPin(MENUPORT,MENU))//PC3 MENU-key press
  460.         {
  461.         delay(50);
  462.         if(!GPIO_ReadInputPin(MENUPORT,MENU))
  463.         {
  464.                 while(!GPIO_ReadInputPin(MENUPORT,MENU));//wait sw release
  465.     MENU_flag++;
  466.                 if(MENU_flag>3)
  467.                 {
  468.                 MENU_flag=0;               
  469.                 }
  470.         }       
  471.   }       
  472.        
  473.        
  474.         if(GPIO_ReadInputPin(MENUPORT,ENTER)==0)//PC3 MENU-key press
  475.         {
  476.                 delay(50);
  477.                 if(!GPIO_ReadInputPin(MENUPORT,ENTER))
  478.                 {
  479.                         while(!GPIO_ReadInputPin(MENUPORT,ENTER));//wait sw release
  480.                         ENTER_flag=1;
  481.                 }               
  482.   }       
  483. }

  484. void Get_Volt_Data(void)//取代void Get_Volt_32Data(void)一次一個data
  485. {
  486.                  if(adc_update_flag==1)//若放在1分鐘則每分鐘紀錄1次
  487.                    {
  488.                           AD_Data_Update();//940us
  489.                                 databuffer=Real_Voltagea;
  490.                                 wbuffer_count++;
  491.                                 putchar((u8)wbuffer_count);
  492.                                 }
  493.                                  write_flag=1;//改成每一秒就寫一次1組資料
  494. }
  495.        



  496. void MENU_0_AD_write (void)//copy form Store_To_EEPROM()
  497. {
  498.         /*write_flag 寫入完成旗標
  499.         databuffer[0] adc存入的資料
  500.         TrData 16bit的 欲寫入資料緩衝
  501.         wbuffer_count 寫入的計數器
  502.         Whigh_Data,Wlow_Data 寫入eprom的緩衝8bit
  503.        
  504.         */
  505.         u16 TrData;
  506.         u8 Whigh_Data,Wlow_Data;       
  507.         FLASH_Unlock(FLASH_MEMTYPE_DATA);
  508.         TrData=databuffer;
  509.         Whigh_Data=(u8)(TrData>>8);
  510.         Wlow_Data=(u8)TrData;
  511.         FLASH_ProgramByte((addr+(wbuffer_count)*2),Whigh_Data);
  512.         FLASH_ProgramByte((addr+(wbuffer_count)*2+1),Wlow_Data);
  513.         if(wbuffer_count>320)
  514.            wbuffer_count=0;
  515.         write_flag=0;//寫入完成
  516. }

  517. void MENU_1_CLR_EPROM (void)
  518. {
  519.         u16 cbuffer_count;
  520.                         for(cbuffer_count=0;cbuffer_count<640;cbuffer_count++)
  521.                 {
  522.                         FLASH_EraseByte(addr+(cbuffer_count));
  523.           }
  524.                 DS_buffer_count=cbuffer_count;
  525. }

  526. /*
  527. 讀取 eeprom的資料copy自 eprom read
  528. Next_Flag 提取下一個data的操作
  529. rbuffer_count 讀取資料的計數值
  530. */
  531. void MENU_2_READ_EPROM (void)//
  532. {
  533.         u8 rhigh_Data,rlow_Data;
  534.        
  535. if(Next_flag==1)
  536. {
  537.          Next_flag=0;         
  538. rhigh_Data=FLASH_ReadByte(addr+(rbuffer_count)*2);          
  539. rlow_Data=FLASH_ReadByte(addr+(rbuffer_count)*2+1);
  540.          
  541.         Volt_From_EPROM=(u16)rhigh_Data;
  542.         Volt_From_EPROM <<=8;
  543.         Volt_From_EPROM +=(u16) rlow_Data;

  544.         rbuffer_count++;
  545.         if(rbuffer_count>320)
  546.         {
  547.         rbuffer_count=0;
  548.         }
  549. }
  550. }       


  551. void MENU_3_Upload_PC (void)
  552. {//read byte
  553.                 u8 high_Data,low_Data;               
  554.         //        int *dataEprom;
  555.                 for(rbuffer_count=0;rbuffer_count<320;rbuffer_count++)
  556.                 {
  557.                                 high_Data=FLASH_ReadByte(addr+(rbuffer_count)*2);          
  558.                                 low_Data=FLASH_ReadByte(addr+(rbuffer_count)*2+1);
  559.                         putchar(high_Data);//
  560.                         putchar(low_Data);//
  561.                         DS_buffer_count=rbuffer_count;
  562.           }       
  563. }


  564.        
  565. void main(void)
  566. {

  567.         GPIOinit();//顯示用
  568.         tim1init();       
  569.         tim4init();
  570.         rim();       
  571.         GPIO_WriteLow(LCMPORT,Latch);;
  572.         GPIO_WriteLow(LCMPORT,SER);;
  573.         DelayMs(100);
  574.         LCD_Init();
  575.         LCD_Clear();
  576.         Uart1_Init();
  577.         //printf("aaa\r\n");
  578. PutString("antlu test uart input!!");
  579. while(1)
  580. {
  581.   switch(MENU_flag)//顯示用
  582.         {               
  583.                 case 0: LCD_Write_String(0,0, "Write Data EPROM");  //顯示紀錄data
  584.                         if(ENTER_flag)
  585.                                                 {
  586.                                                         wbuffer_count=0;
  587.                                                         ENTER_flag=0;
  588.                                                 }
  589.                                                 Get_Volt_Data();//紀錄data
  590.                                                 MENU_0_AD_write ();
  591.                                                 Real_Voltagea= databuffer; //顯示目前電壓值
  592.                                                 DS_buffer_count= wbuffer_count; //顯示目前寫入位址

  593.                                                 break;
  594.                 case 1:        LCD_Write_String(0,0, "CLEAR EPROM DATA "); //清除紀錄data
  595.                         wbuffer_count=0;
  596.                         if(ENTER_flag)
  597.                                                 {
  598.                                                         MENU_1_CLR_EPROM ();
  599.                                                         ENTER_flag=0;
  600.                                                 }               
  601.                                                 DS_buffer_count=cbuffer_count;
  602.                         break;       
  603.                 case 2: LCD_Write_String(0,0, "READ EPROM DATA ");//紀錄讀出       
  604.                         if(ENTER_flag)
  605.                                                 {
  606.                                                         Next_flag=1;
  607.                                                         MENU_2_READ_EPROM();
  608.                                                         ENTER_flag=0;
  609.                                                         putchar((u8)rbuffer_count);
  610.                                                 }       
  611.                                                 Real_Voltagea= Volt_From_EPROM;
  612.                                                 DS_buffer_count=rbuffer_count;                                                       
  613.                
  614.                                                 break;
  615.                 case 3:LCD_Write_String(0,0, " UPLOAD to PC   ");//data 上傳pc
  616.                         if(ENTER_flag)
  617.                                                 {
  618.                                                         MENU_3_Upload_PC ();
  619.                                                         ENTER_flag=0;
  620.                                                 }       
  621.                                                 DS_buffer_count=rbuffer_count;                                               
  622.                                           break;
  623.                 default:break;
  624.         }
  625.                
  626. //  ans = getchar();
  627. //        putchar(ans);
  628. // if(ans=='c')
  629. //        {
  630. //   PutString("I got the c!");       
  631. //         PutString("antlu ans uart input!!");
  632. //        }

  633. }       
  634. }


  635. @far @interrupt void TIM1_OVF_IRQ(void)
  636. {
  637.         tim1svc();
  638. }

  639. @far @interrupt void TIM4_OVF_IRQ(void)
  640. {
  641.         tim4svc();
  642. }




  643. #ifdef USE_FULL_ASSERT

  644. /**
  645.   * @brief  Reports the name of the source file and the source line number
  646.   *   where the assert_param error has occurred.
  647.   * @param file: pointer to the source file name
  648.   * @param line: assert_param error line source number
  649.   * @retval : None
  650.   */
  651. void assert_failed(u8* file, u32 line)
  652. {
  653.   /* User can add his own implementation to report the file name and line number,
  654.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  655.   /* Infinite loop */
  656.   while (1)
  657.   {
  658.   }
  659. }
  660. #endif

  661. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
複製代碼


評分

2

查看全部評分

 樓主| 發表於 2014-11-13 22:34:24 | 顯示全部樓層
chlu 發表於 2014-11-13 06:51 AM
紀錄模式 每分鐘紀錄一電壓值,並存入EEPROM 總數320個資料
EEPROM 不是有次數限制嗎? 以100000次來算好像2 ...

CHLU大:
  因為小弟的功力還不會把資料寫近 93C66 或是 24C64 等外加的EEPROM 所以就先用這個內建的EEPROM, STM8S 的庫函數我還用的不順,它的I2C非常複雜,我快放棄了!!
紀錄電壓一般不會一值掛著,只要是要抓取待測物的特性!! 這還需要和 VB搭配,只是我還不會 VB...
 樓主| 發表於 2014-11-13 22:37:37 | 顯示全部樓層
xiaolaba 發表於 2014-11-13 08:34 AM
看到你的那個常式 void DigitalFiltering(void)

給你看看這個, 好像很有用的, 類似移動平均法, 也是一階 ...

xiaolaba 大:
   我數學不好,我慢慢消化看看!!  感謝!!
發表於 2014-11-13 22:47:15 | 顯示全部樓層
antlu 發表於 2014-11-13 10:34 PM
CHLU大:
  因為小弟的功力還不會把資料寫近 93C66 或是 24C64 等外加的EEPROM 所以就先用這個內建的EEPRO ...

阿乾兄,不用VB啦!
使用神級程式「超級終端機」就行了,
COM PORT輸出,超級終端機接收後,
匯出純文字檔,再使用EXCEL類程式記錄及分析就行了!
還可以畫圖表喔!
 樓主| 發表於 2014-11-13 22:48:07 | 顯示全部樓層
jojoling 發表於 2014-11-13 11:10 AM
做Filter 有問題

for(i=2;i

JOJOLING大:
  感謝再感謝!!沒有你,我還在漫漫長夜中摸索...
 樓主| 發表於 2014-11-13 23:13:02 | 顯示全部樓層
jason680 發表於 2014-11-13 03:55 PM
看到其他大大的回應...
這裏也提供一個簡單的想法...

jason680大:
  感謝!! 這樣可以省下不少時間!! 也是另類的過濾方法!!
  我還有一個需求就是320個全值裡也需要找出最大值 最小值 如此一來可以作為紀錄資料的參考!!
 樓主| 發表於 2014-11-13 23:18:04 | 顯示全部樓層
本文章最後由 antlu 於 2014-11-13 11:20 PM 編輯

還有一個想法就是"沒有顯示幕"一開機就一直紀錄到斷電為止或是320筆完整之後就停止,只有接到PC時候直接上傳,這樣可以省下元件和空間!!
 樓主| 發表於 2014-11-13 23:23:41 | 顯示全部樓層
fatzeros 發表於 2014-11-13 10:47 PM
阿乾兄,不用VB啦!
使用神級程式「超級終端機」就行了,
COM PORT輸出,超級終端機接收後,

F0S大:
    下次有機會教教我,這樣就太完美了!!
   有一個小問題,我是每一個資料存兩個BYTE 可能還要作合併,以及16進位轉10進位的問題...
發表於 2014-11-14 09:57:11 | 顯示全部樓層
antlu 發表於 2014-11-13 11:23 PM
F0S大:
    下次有機會教教我,這樣就太完美了!!
   有一個小問題,我是每一個資料存兩個BYTE 可能還要作合 ...

搞定STM8的UART輸出,設定好TX、RX腳位,
使用PL2303或是CH340的UART TO USB輸出連接到電腦裡,
連接好TX、RX,最簡單的就是使用STC MCU的下載器或是CP2102小板,
設定好電腦裡的PUTTY或是超級終端機,COM PORT、BAUDRATE等等,
將MCU的輸出內容輸出至純文字檔!
純文字檔的格式,要在STM8的程序裡定義好,不論是十進位還是十六進位皆可,
但是,每次輸出都要有個間隔符號,可以使用逗號(,)等,
再來就是使用EXCEL類的試算表軟體,開啟純文字檔輸入,
再來,就是基本的文書作業了!

以上就是基本上的流程及概論,看看有沒有其他老師有什麼不同的見解或補充了!
您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

關閉

站長小叮嚀上一條 /1 下一條

禁閉室|手機版|連繫我們|痞酷網電子技術論壇

GMT+8, 2024-4-28 08:30 AM , Processed in 0.090181 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.