2014年12月24日 星期三

STM32 DMA軟體式FIFO程式

用在通信及ADC上,使用DMA循環式架構。利用DMA上的計數器做為FIFO控制。
其中USART1_BUFFER_SIZE,要設定在DMA的大小中。
 USART1_Buffer[]也是DMA所使用的。

unsigned short last_count;

void Reset_USART1_Buffer(void)
{
    last_count = DMA_GetCurrDataCounter(DMA2_Stream5);
}

int Get_USART1_Value(unsigned char *Value)
{
    unsigned short current_count;
    int  pos;

    current_count = DMA_GetCurrDataCounter(DMA2_Stream5);
    if ( current_count != last_count )
    {
        pos = USART1_BUFFER_SIZE - last_count;
        *Value = USART1_Buffer[pos];
        last_count--;
        if (last_count <= 0)
        {
            last_count = USART1_BUFFER_SIZE;
        }
        return -1;
    }
    else
    {
        return 0;
    }
}


因為已用DMA,軟體過一段時間去收就好了,完全無需使用中斷。

2014年12月22日 星期一

Encoder使用

這個月被二位網友問到Encoder問題。
Bee看過很多MCU工程師寫的程式,大部分工程師將I/O暫存器當RAM用。
但實際上硬體不穩定時,就查得要死要活的,很難穩定系統,又不知問題在那裏。
Bee也是過來人,因為早期Bee也寫過不穩定的硬體(用FPGA),軟體上吃了大虧,自此養成必要時才動硬體暂存器的習慣。
也就是使用Encoder,必要時才讀,再轉成32位元變數(64位元也可以),以32位元為其他軟體的依據。
這招不僅是減少對硬體的依賴度,也增加不同平台的可移植性。
同樣的Encoder程式,用在數個案子內:
1. 8051,使用中斷方式解Encoder,可用。
2. FPGA,使用I/O讀取24位元,可用。
3. STM32,內建Encoder,16位元,可用。
上層馬達控制程式完全不用修改。

其中有幾行連博士也覺得神奇,找過各大網站,就是找不到為何可以用。
以STM32系統為例:

int Encoder_Count;
unsigned short Last_Encoder;

void GetEncoder(void)
{
    unsigned short Encoder = 0;
    int Encoder_Diff;
   
    Encoder = TIM_GetCounter(ENC_TIMER);
    Encoder_Diff = (short)(Encoder - Last_Encoder);
    Last_Encoder = Encoder;
    Encoder_Count += Encoder_Diff;
}

Encoder_Count就是32位元Encoder的值,一樣不管Encoder暫存器是16/24位元,都先轉成32位元。
之後再重新計算,看是單向運動,圓週運動,基本上32位元都不會掉精度。

Encoder_Diff = (short)(Encoder - Last_Encoder);
此行則是利用unsigned在計算時underflow/overflow的特性得到差值,這是一般人不會使用的。

2014年12月6日 星期六

在FATFS Sample中新增PC檔案交換功能

FATFS可以在PC上模擬,是利用記憶體做的一個Disk,但創造後是空的,難以做其他實驗。所以新增二個指令可以將檔案搬進Fatfs系統及搬出Fatfs系統。

搬入指令fy,程式碼如下:

            case 'y' :    /* fy <src_name> <dst_name> - Copy a file from PC*/
                while (*ptr == ' ') ptr++;
                ptr2 = _tcschr(ptr, ' ');
                if (!ptr2) break;
                *ptr2++ = 0;
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Opening PC file \"%s\""), ptr);
                fp = fopen(ptr,"rb");
                _tprintf(_T("\n"));
                if (!fp) {
                    _tprintf(_T("Open Fail!\n"));
                    break;
                }
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Creating \"%s\""), ptr2);
                res = f_open(&file[1], ptr2, FA_CREATE_ALWAYS | FA_WRITE);
                _tprintf(_T("\n"));
                if (res) {
                    put_rc(res);
                    f_close(&file[0]);
                    break;
                }
                _tprintf(_T("Copying..."));
                p1 = 0;
                for (;;) {
                    s1 = fread(Buff, 1, sizeof Buff, fp);
                    if (s1 == 0) break;   /* error or eof */
                    res = f_write(&file[1], Buff, s1, &s2);
                    p1 += s2;
                    if (res || s2 < s1) break;   /* error or disk full */
                }
                _tprintf(_T("\n"));
                if (res) put_rc(res);
                fclose(fp);
                f_close(&file[1]);
                _tprintf(_T("%lu bytes copied.\n"), p1);
                break;


搬出指令fz,程式碼如下:
            case 'z' : /* fz <src_name> <dst_name> - Copy a file to PC*/
                while (*ptr == ' ') ptr++;
                ptr2 = _tcschr(ptr, ' ');
                if (!ptr2) break;
                *ptr2++ = 0;
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Opening \"%s\""), ptr);
                res = f_open(&file[0], ptr, FA_OPEN_EXISTING | FA_READ);
                _tprintf(_T("\n"));
                if (res) {
                    put_rc(res);
                    break;
                }
                while (*ptr2 == ' ') ptr2++;
                _tprintf(_T("Creating PC file \"%s\""), ptr2);
                fp = fopen(ptr2,"wb");
                _tprintf(_T("\n"));
                if (!fp) {
                    _tprintf(_T("Open Fail!\n"));
                    break;
                }
                _tprintf(_T("Copying..."));
                p1 = 0;
                for (;;) {
                    res = f_read(&file[0], Buff, sizeof Buff, &s1);
                    if (res || s1 == 0) break;   /* error or eof */
                    s2 = fwrite(Buff, 1, s1,fp);
                    p1 += s2;
                    if (s2 < s1) break;   /* error or disk full */
                }
                _tprintf(_T("\n"));
                if (res) put_rc(res);
                f_close(&file[0]);
                fclose(fp);
                _tprintf(_T("%lu bytes copied.\n"), p1);
                break;

程式基礎是從fx指令改出來的。