用在通信及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月24日 星期三
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的特性得到差值,這是一般人不會使用的。
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指令改出來的。
搬入指令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指令改出來的。
訂閱:
文章 (Atom)