![](http://uphotos.eepw.com.cn/Rancho/thumb/avatar.jpg)
![](http://uphotos.eepw.com.cn/campozeng/thumb/avatar.jpg)
![](http://uphotos.eepw.com.cn/campozeng/thumb/avatar.jpg)
使用DMA (Direct Memory Access) controller 可以不通過CPU就可以將外設的數據傳到Ram,或者將RAM的數據傳送到外設。
這樣就可以高速傳送大量數據,也將可以做到real-time了。
下面我們學習一下怎麼用DMA
1、我們定義兩個寄存器,把它在Ram中的地址固定下來,如下圖:
2、我們使用Applilet生成基礎代碼,首先們們定義DMA1,將AD轉換的結果傳送到ADCBuffer,設置如下,注意藍色框中部分:
3、定義DMA1,將UART2/RXD2數據傳送到RX2Buffer,設置如下,注意藍色框中部分:
4、然后生成代碼,加到我們的項目中就可以用了,是不是很簡單呢。
調用下面一些函數就可以使用了:
void DMA0_Init(void);
void DMA0_Enable(void);
void DMA0_Disable(void);
void DMA0_Hold(void);
void DMA0_Restart(void);
MD_STATUS DMA0_CheckStatus(void);
void DMA0_SoftwareTriggerOn(void);
MD_STATUS DMA0_SetData(UCHAR sfraddr, USHORT ramaddr, USHORT count);
void DMA0_UserInit(void);
__interrupt void MD_INTDMA0(void);
void DMA1_Init(void);
void DMA1_Enable(void);
void DMA1_Disable(void);
void DMA1_Hold(void);
void DMA1_Restart(void);
MD_STATUS DMA1_CheckStatus(void);
void DMA1_SoftwareTriggerOn(void);
MD_STATUS DMA1_SetData(UCHAR sfraddr, USHORT ramaddr, USHORT count);
void DMA1_UserInit(void);
__interrupt void MD_INTDMA1(void);
![](http://uphotos.eepw.com.cn/campozeng/thumb/avatar.jpg)
IIC的協議就不多描述了,有興趣的朋友可以找相關資料看。
下面開始:
首選把EERPOM的SCL/SDA連接到P60/SCLA0和P61/SDAA0,把A0/A1/A2都接到GND,把EEPROM的slave址設為了0xA0
1、Applilet生成基礎代碼
首先設定MCU的工作時鐘,如下圖:
IICA0模式選擇為Single Master
IICA0設定如下圖
為了測試簡單,先把WDT關了
然后點Generate code,生成后用IAR打開*.eww文件
2、打開CG_serial_user.c文件,改一下代碼,如下圖藍色框中的代碼是我增加進去的,用于發送和接收和完成的標志位
3、打開CG_main.c文件,開始寫我們自己的代碼,如下圖,在頭部定義一此要用的寄存器,見藍色框中部份:
4、然后寫一個簡單的測試程序來測試,我現在把程序寫到main函數中,函數如下:
下面函數的功能主要是:先寫一個字節的數據到EEPROM,寫完后再把數據讀出來,如果讀出的數據與寫進的數據相等,剛把RL78/G13上的LED D2反轉(亮變滅,滅則變亮)。
void main(void)
{
/* Start user code. Do not edit comment generated here */
UCHAR Status,EEAddress;
USHORT i;
__low_level_init(); // init. system
EEAddress=0xA0; // define eeprom slave address
IICWriteCompleteFlag=0; // if write data complete, =1
IICReadCompleteFlag=0; // if read data complete, =1
PU7_bit.no7 = 1;
PM7_bit.no7 = 0;
P7_bit.no7=1; //define the LED on RL78/G13 board
for(i=0;i<50000;i++) //delay
{
NOP();
}
while (1U)
{
if(IICWriteCompleteFlag==0 && IICReadCompleteFlag==0) //if idle
{
IICWriteCompleteFlag=2;
IICWriteBuffer[0]=0x00; //EEPROM add ,thd address where to write data
for(i=1;i<15;i++)
{
IICWriteBuffer[i]=i; //the data what to write
}
/** write 2 byte data,first is address, the second byte is data**/
Status=IICA0_MasterSendStart(EEAddress, IICWriteBuffer, 2, 150);
if(Status != MD_OK)
{
IICWriteCompleteFlag=0;
}
}
else if(IICWriteCompleteFlag==1) //if write complete
{
IICWriteCompleteFlag=0;
IICReadCompleteFlag=2;
for(i=0;i<50000;i++) //delay for eeprom to access the data
{
NOP();
}
for(i=0;i<50000;i++) //delay for eeprom to access the data
{
NOP();
}
/* send address whred to read*/
Status=IICA0_MasterSendStart(EEAddress, IICWriteBuffer, 1, 150);
if(Status != MD_OK)
{
IICReadCompleteFlag=0;
}
else
{
for(i=0;i<50000;i++) //delay for eeprom to access the data
{
NOP();
}
while(IICWriteCompleteFlag==0); // wait write address complete
IICWriteCompleteFlag=0;
/* read out 1 byte data*/
Status=IICA0_MasterReceiveStart(EEAddress, IICReadBuffer, 1, 150);
if(Status!=MD_OK)
{
IICReadCompleteFlag=0;
}
}
}
else if(IICReadCompleteFlag==1) //if read complete
{
IICReadCompleteFlag=0;
if(IICReadBuffer[0]==IICWriteBuffer[1])
{
/*if the read out data equ the data writed before*/
/* flash the led on the rl78/G13 board*/
P7 ^= 0x80;
}
}
for(i=0;i<25000;i++) //delay
{
NOP();
}
}
/* End user code. Do not edit comment generated here */
}
IICA0 EEPROM讀寫程序在下面下載:
——回复可见内容——
![](http://uphotos.eepw.com.cn/campozeng/thumb/avatar.jpg)
IO 模擬IIC 讀寫EEPROM
內置的IICA0/IIC00這些模塊測試一下,好像不太好用,樓上有文檔供大家學習。
現在教大家用IO模擬IIC來讀寫EEPROM.
首先定義SCL/SDA:
#define SDA P7_bit.no5
#define SDA_INPUT PM7_bit.no5
#define SCL P7_bit.no6
#define SCL_INPUT PM7_bit.no6
首先,我們將會用到以下一些函數:
void CreateIICPort(void);
這個涵數用于初始化要用到的IO狀態
void DelayUs(USHORT US);
用于延時DelayUs(5)為延時約5us.
void Start_I2c(void);
啟動IIC總線
void Stop_I2c(void);
停止IIC總線
void SendByte(UCHAR c);
發送一個字節數據
UCHAR RcvByte(void);
接收一個字節數據
void Ack_I2c(UCHAR a);
發送應答位
UCHAR ISendStrB(UCHAR sla,USHORT suba,UCHAR *s,UCHAR no);
// for 24C32/64/128/256
// sla 為 EEPROM的slave 址
// suba 為要寫進數據的地址,大于等于24C32地址是16位的
// *s 為要寫進的數據的頭地址
// no 為要寫進的字節數量,如一次寫進16 bytes,則no=16
此函數用于向EEPROM寫數據,不同的EEPROM 頁編程的大小是不一樣的,大家可以參考datasheet,如24c32一次可寫進16byte 的數據,但必須從每頁的頭地址開始寫
UCHAR ISendStrS(UCHAR sla,UCHAR suba,UCHAR *s,UCHAR no);
//for 24C02/04/08/16/
此函數用于向EEPROM寫數據,suba為8位
UCHAR IRcvStrB(UCHAR sla,USHORT suba,UCHAR *s,UCHAR no);
//for 24C32/64/128/256
此函數用于向EEPROM讀數據,suba為16位
UCHAR IRcvStrS(UCHAR sla,UCHAR suba,UCHAR *s,UCHAR no);
//for 24C02/04/08/16/
此函數用于向EEPROM讀數據,suba為8位
大家學會了上面幾個函數就可以隨意讀寫EEPROM了。
如果想進一步學習上面的函數是怎麼寫出來的,就要參考一下IIC時序了
如大家對著下圖的Start condition和下面的Start_I2c函數就很容易理解了:
/*******************************************************************
Start iic bus
********************************************************************/
void Start_I2c(void)
{
SDA=1; /* send start data signal */
SCL=1;
DelayUs(5); /* wait more than 4.7us*/
SDA=0; /* send start signal */
DelayUs(5); /* wait more than 4.7us*/
SCL=0;
}
是不是很簡單呢?
更多的函數,大家可以下面程序回去研究一下,也可以直接運行于RL78/G13開發板上
每一次讀寫正確,板上的D2 LED會翻轉一次。
——回复可见内容——
![](http://uphotos.eepw.com.cn/campozeng/thumb/avatar.jpg)
受控于上位機的直流電機
視頻:http://v.eepw.com.cn/video/play/id/1963
下面我們基于RL78/R13開發板來做一個用上位機控制直流電機正反轉,加速,減速,暫停的程序。
1、首先我們按下面的原理圖焊接一個H桥电路
從電路上我們可以看出:
當PWM1為高電平,PWM2為低電平時,電流經T2流過直流電機再經T5流到地
當PWM1為低電平,PWM2為高電平時,電流從經T1流過直流電機再經T6流到地
當PWM1,PWM2同時為高或低電平時,電機就可以停轉了
這樣我們就可以實現了直流電機轉向的控制了。
當PWM1為100% Duty,PWM2為50% Duty時,馬達的轉速就減低了。
2、很明顯,要實現不同轉速和轉向的控制,我們需要兩路PWM,我們把PWM1/PWM2分別連接到RG78/G13開發板的P16/TO01和 P31/TO03
因為RG78/G13開發板的UART2連接到UART轉USB上去,所以我們可以很方便的用UART2與上位機進行通訊。
到這里硬件電路就建好了,下面開始軟件開發。
3、為了加快速度,我們用Applilet生成基本代碼
4、系統時鐘設置
設定系統時鐘為32M,如下圖:
為了簡單,關閉WDT,如下圖:
5、設置PWM通道
定義Channel0和Channel2為PWM Master通道,Channel1和Channel3就自動設為Slave通道了,設置如下圖:
設置Master通道Channel0和Channel2的Cycle均為100us,Channel0的設置如下圖,Channel2的設置與Channel0相同:
設置Slave 通道Channel1和Channel3的Duty value均為50%,Channel1的設置如下圖,Channel3的設置與Channel1相同:
6、設置UART2
這次實驗只需要接收命令,所以我把UART2設為僅接收,如下圖:
UART2的參數設置如下圖:
7、點擊”Generate”生成代碼
8、用IAR打開生成的“PWM.eww”文件。
9、在主文件“CG_main.C”定義寄存器,如下圖,藍色框中的代碼是我增加進去的:
10、串口接收代碼編寫:
CG_main.c中定義的寄存器,有兩個CG_serial_user.c這個文件也要用到,要在頭部定義一下,如下:
extern UCHAR DataReceive;
extern UCHAR RXBuffer[2];
11、在CG_serial_user.c中的UART2_ReceiveEndCallback函數增加以下代碼:
藍色部份是我增加的,主要功能是接收到上位機的數據后,先停止UART2接收,然后設置標志位DataReceive,以便主程序處理數據
void UART2_ReceiveEndCallback(void)
{
/* Start user code. Do not edit comment generated here */
UART2_Stop();
DataReceive=1;
/* End user code. Do not edit comment generated here */
}
最后在CG_main.c這個文件里寫一個簡單的測試程序如下:
void main(void)
{
/* Start user code. Do not edit comment generated here */
__low_level_init(); //初始代系統
Direction=0; //定義馬達的初始轉向
MotorDuty=50; //定義馬達的初始轉速
TAU0_Channel3_ChangeDuty(100); //通道3為100% duty輸出
TAU0_Channel1_ChangeDuty(100-MotorDuty); //通道1根據初始化數據輸出
TAU0_Channel0_Start();
TAU0_Channel2_Start(); //啟動PWM模塊
DataReceive=0;
UART2_ReceiveData(RXBuffer, 2); //等待接收上位機的命令,命令為2 byte數據
UART2_Start(); //啟動UART2模塊
while (1U)
{
if(DataReceive==1) //如接收到命令數據,進行如下處理
{
if(RXBuffer[0]=='%' && RXBuffer[1]=='F') // forward command
{
Direction=0;
TAU0_Channel1_ChangeDuty(100);
TAU0_Channel3_ChangeDuty(100-MotorDuty);
}
else if(RXBuffer[0]=='%' && RXBuffer[1]=='B') // backward command
{
Direction=1;
TAU0_Channel1_ChangeDuty(100-MotorDuty);
TAU0_Channel3_ChangeDuty(100);
}
else if(RXBuffer[0]=='%' && RXBuffer[1]=='S') // stop command
{
TAU0_Channel1_ChangeDuty(100);
TAU0_Channel3_ChangeDuty(100);
}
else if(RXBuffer[0]=='%' && RXBuffer[1]=='+') // speed up command
{
MotorDuty +=10;
if(MotorDuty>100)
{
MotorDuty=100;
}
if(Direction==0)
{
TAU0_Channel1_ChangeDuty(100);
TAU0_Channel3_ChangeDuty(100-MotorDuty);
}
else
{
TAU0_Channel1_ChangeDuty(100-MotorDuty);
TAU0_Channel3_ChangeDuty(100);
}
}
else if(RXBuffer[0]=='%' && RXBuffer[1]=='-') // speed down command
{
MotorDuty -=10;
if(MotorDuty<30)
{
MotorDuty=30;
}
if(Direction==0)
{
TAU0_Channel1_ChangeDuty(100);
TAU0_Channel3_ChangeDuty(100-MotorDuty);
}
else
{
TAU0_Channel1_ChangeDuty(100-MotorDuty);
TAU0_Channel3_ChangeDuty(100);
}
}
else
{
NOP();
}
DataReceive=0;
UART2_ReceiveData(RXBuffer, 2);
UART2_Start();
}
}
/* End user code. Do not edit comment generated here */
}
這樣就大功告成了,把程序下載到開發板,打開串口助手開始測試吧
記得把開發板上的J6/J7/J8/J9 接到2-3
通過串口助手發送以下命令進行測試
%F
%S
%B
%+
%-
Campozeng
2012-9-12
本文的PDF文檔和完整代碼從下面鏈接下載
——回复可见内容——
——回复可见内容——
下圖是我接H橋電路和RL78/G13開發板,簡單了點,但可以用的哦
回复
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |