?? main.cpp
字號:
/*-----------------------------------------
DSP菜鳥的第1個通過實驗的DSP C++演示程序
菜農 HotPower@126.com
2005.6.26 15:58 于西安大雁塔村隊部
菜地: http://hotpower.21ic.org
-----------------------------------------*/
#include <cstdio> //C語言可以用stdio.h
#include <cstring>//C語言可以用string.h
#include "C5402DEF.h"//DSP菜鳥HotPower創建
#include "class.h"
#define ccsdebug 0//1--IO模擬SPI; 0--硬件McBSP模塊
extern "C" interrupt void Timer0Isr();//注意加extern "C"
extern "C" interrupt void Timer1Isr();
extern "C" interrupt void Eint0Isr();
extern "C" interrupt void Eint1Isr();
extern "C" interrupt void Eint2Isr();
extern "C" interrupt void Eint3Isr();
SystemObj::SystemObj(void)
{
Disable();//關中斷
SREG->IMR = 0x0000;//
SREG->IFR = 0xffff;
//設置0x0080為中斷向量表首址,在第2個128頁內。
SREG->PMST = (0x01 << PMST_IPTR) | (1 << PMST_MP_MC) | (1 << PMST_OVLY);
// SREG->PMST |= (1 << PMST_DROM);//數據可const.
/*---------------------------------------------------------------------------
若:設置0x0100為中斷向量表首址,在第3個128頁內。
則:*.cmd文件應該改為:
PAGE 0: VECS: origin=0x0100, length=0x66
則:
SREG->PMST = (0x02 << PMST_IPTR) | (1 << PMST_MP_MC) | (1 << PMST_OVLY);
----------------------------------------------------------------------------*/
SystemInit();//系統初始化
}
void SystemObj::SystemInit(void)
{
PllInit();//PLL初始化
TIMER0Init();
TIMER1Init();
EintInit();
/*--------------------------------------------------------
注意以下2個變量的作用域的不同
--------------------------------------------------------*/
if (::SystemRamTest != 0x55aa) {//全局變量SystemRamTest
::SystemRamTest = 0x55aa;//改寫全局變量
}
if (SystemRamTest != 0x55aa) {//類成員變量SystemRamTest
SystemRamTest = 0x55aa;//改寫類成員變量
}
::IOXF = 0;
}
void SystemObj::PllInit(void)
{
volatile unsigned int start;
SREG->SWWSR = 0x2000;
do {
SREG->CLKMD = 0;
__nop();
}
while(SREG->CLKMD & (1 << CLKMD_PLLSTATUS));
// SREG->CLKMD = (0 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 << CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//10M
SREG->CLKMD = (9 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 << CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//100M
// SREG->CLKMD = (14 << CLKMD_PLLMUL) | (30 << CLKMD_PLLCOUNT) | (1 << CLKMD_PLLONOFF) | (1 << CLKMD_PLLNDIV) | (1 << CLKMD_PLLSTATUS);//150M
for (start = 0; start < 10000; start ++);//等待外設上電復位正常結束
}
void SystemObj::TIMER0Init(void)
{
TIMER0->TCR |= (1 << TCR_TSS);//關閉定時器0
TIMER0->PRD = 60000;//設置定時周期
TIMER0->TCR &= ~(1 << TCR_TSS);//啟動定時器0
SREG->IMR |= (1 << IMR_TINT0);//允許TINT0中斷
}
void SystemObj::TIMER1Init(void)
{
TIMER1->TCR |= (1 << TCR_TSS);//關閉定時器1
TIMER1->PRD = 55000;//設置定時周期
TIMER1->TCR &= ~(1 << TCR_TSS);//啟動定時器1
SREG->IMR |= (1 << IMR_TINT1);//允許TINT1中斷
}
void SystemObj::EintInit(void)
{
SREG->IMR |= (1 << IMR_INT0);//允許INT0中斷
SREG->IMR |= (1 << IMR_INT1);//允許INT1中斷
SREG->IMR |= (1 << IMR_INT2);//允許INT2中斷
SREG->IMR |= (1 << IMR_INT3);//允許INT3中斷
}
LcdObj::LcdObj(void)
{
LcdInit();
}
void LcdObj::LcdSpiSetup(void)
{
#if (ccsdebug == 0)
/*-----------------------------------------------------------
硬件McBSP模塊配置為SPI接口
實驗目的:
演練硬件McBSP模塊配置為SPI接口的應用。
------------------------------------------------------------*/
McBSP1->SPSA = SPCR1;
McBSP1->SPSD = 0;
// McBSP1->SPSD &= ~(1 << SPCR1_RRST);//禁止串口接收
_delay_loop_(1);//延時等待
McBSP1->SPSA = SPCR2;
McBSP1->SPSD = 0;
// McBSP1->SPSD &= ~(1 << SPCR2_XRST);//禁止串口發送
_delay_loop_(1);//延時等待
McBSP1->SPSA = SPCR1;
McBSP1->SPSD = (0x02 << SPCR1_CLKSTP);//CLKSTP=10b
_delay_loop_(1);//延時等待
McBSP1->SPSA = PCR;
McBSP1->SPSD = (1 << PCR_FSXM) //設置FSX引腳為輸出,控制LCD12864的片選信號SS
| (0 << PCR_FSXP) //FSX引腳平時輸出低電平(LCD12864的片選信號SS無效)
| (1 << PCR_CLKXM) //設置CLKX引腳為輸出
| (1 << PCR_CLKXP);//CLKXP引腳平時輸出高電平
_delay_loop_(1);//延時等待
McBSP1->SPSA = SRGR1;
McBSP1->SPSD = (0x07 << SRGR1_FWID) //0x00~0x07~0xff
| (0x80 << SRGR1_CLKGDV);//速率0x80
_delay_loop_(1);//延時等待
McBSP1->SPSA = SRGR2;
McBSP1->SPSD = (1 << SRGR2_CLKSM);//
_delay_loop_(1);//延時等待
McBSP1->SPSA = RCR1;
McBSP1->SPSD = (0x00 << RCR1_RFRLEN1);//8BIT
_delay_loop_(1);//延時等待
McBSP1->SPSA = XCR1;//延時等待
McBSP1->SPSD = (0x00 << XCR1_RFRLEN1);//8BIT
_delay_loop_(1);//延時等待
McBSP1->SPSA = RCR2;
McBSP1->SPSD = (0x02 << RCR2_RDATDLY);//0x01
_delay_loop_(1);//延時等待
McBSP1->SPSA = XCR2;
McBSP1->SPSD = (0x02 << XCR2_RDATDLY);//0x01
_delay_loop_(1);//延時等待
McBSP1->SPSA = SPCR2;
McBSP1->SPSD |= (1 << SPCR2_GRST) | (1 << SPCR2_XRST) | (1 << SPCR2_FRST);
_delay_loop_(1);//延時等待
#else
/*-----------------------------------------------------------
硬件McBSP模塊配置為普通IO軟件模擬SPI時序
實驗目的:
演練硬件McBSP模塊配置為普通IO的應用.以備IO緊缺時急用。
------------------------------------------------------------*/
McBSP1->SPSA = SPCR1;
McBSP1->SPSD = 0;
McBSP1->SPSD &= ~(1 << SPCR1_RRST);//禁止串口接收
McBSP1->SPSA = SPCR2;
McBSP1->SPSD = 0;
McBSP1->SPSD &= ~(1 << SPCR2_XRST);//禁止串口發送
McBSP1->SPSA = PCR;
McBSP1->SPSD = (1 << PCR_XIOEN) | (1 << PCR_RIOEN);//設置收發為IO接口,DX輸出,DR,CLKS輸入
McBSP1->SPSD |= (1 << PCR_FSXM) | (1 << PCR_CLKXM);//設置FSX,CLKX可做IO輸出
McBSP1->SPSD |= (1 << PCR_FSRM) | (1 << PCR_CLKRM);//設置FSR,CLKR可做IO輸出
McBSP1->SPSD &= ~(1 << PCR_FSXP);//FSX信號=0
McBSP1->SPSD |= (1 << PCR_CLKXP);//CLKX信號=1
McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信號=1
#endif
}
void LcdObj::LcdInit(void)
{
_delay_loop_(1000);//延時等待
LcdSpiSetup();
/*---------------------------------------------------
LCD模塊上電等待延時
----------------------------------------------------*/
_delay_loop_(1000);//延時等待
LcdClearBuffer();
LcdSendCommand(0x20);//發送4位控制命令
// LcdSendCommand(0x30);//發送8位控制命令//與8位4位無關!!!
LcdSendCommand(0x02);//發送位址歸位命令,設定DDRAM位址計數器為0
LcdSendCommand(0x04);//發送進入點命令
LcdSendCommand(0x0c);//發送開顯示關光標命令
LcdSendCommand(0x01);//發送清除顯示命令
LcdSendCommand(0x80);//發送設定DDRAM地址0x00命令
//Keil C51漢字0xfd出錯測試
// SetLcdDisplayPos(0, 0);//漢字定位到上行左端
// LcdDisplay("褒餅昌除待諜洱俘");
// LcdDisplay("1234567812345678");
SetLcdDisplayPos(1, 0);//漢字定位到上行左端
LcdDisplay("庚過糊積箭燼君魁");
// LcdDisplay("1234567812345678");
SetLcdDisplayPos(2, 0);//漢字定位到上行左端
LcdDisplay("例籠慢謬凝琵訖驅");
// LcdDisplay("1234567812345678");
SetLcdDisplayPos(3, 0);//漢字定位到上行左端
// LcdDisplay("三升數她聽妄錫淆");
LcdDisplay("1234567812345678");
}
void LcdObj::LcdSend(unsigned char cData)
{
cData &= 0xff;
#if (ccsdebug == 0)
McBSP1->DXR1 = cData;//發送串行數據或命令
_delay_loop_(1);//延時等待
McBSP1->SPSA = SPCR2;
while((McBSP1->SPSD & (1 << SPCR2_XRDY)) == 0) {//等待發送結束
__nop();
__nop();
}
_delay_loop_(1);//延時等待
#else
unsigned int i;
McBSP1->SPSA = PCR;
for (i = 0; i < 8; i ++) {
McBSP1->SPSD &= ~(1 << PCR_CLKXP);//CLKX信號=0
_delay_loop_(1);//延時等待
if (cData & 0x80) {//MSB最高位為1時
McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信號=1
}
else {
McBSP1->SPSD &= ~(1 << PCR_DX_STAT);//DX信號=0
}
cData <<= 1;
_delay_loop_(1);//延時等待
McBSP1->SPSD |= (1 << PCR_CLKXP);//CLKX信號=1
_delay_loop_(1);//延時等待
}
McBSP1->SPSD |= (1 << PCR_DX_STAT);//DX信號=1
_delay_loop_(1);//延時等待
#endif
}
/*--------------------------------------------------------
發送8位LCD控制命令
--------------------------------------------------------*/
//__inline
void LcdObj::LcdSendCommand(unsigned char cCommand)
{
/*--------------------------------------------------------
發送同步脈沖11111 WR(0) RS(0) 0發送順序從左至右)
--------------------------------------------------------*/
#if (ccsdebug == 1)
McBSP1->SPSD |= (1 << PCR_FSXP);//IO模擬控制FSX信號=1
_delay_loop_(1);//延時等待
#endif
LcdSend(0xf8);//發送LCD控制命令
LcdSend(cCommand & 0xf0);//發送高4位LCD控制命令
LcdSend((cCommand << 4) & 0xff);//發送低4位LCD控制命令
#if (ccsdebug == 1)
McBSP1->SPSD &= ~(1 << PCR_FSXP);//IO模擬控制FSX信號=0
#endif
if (cCommand == 0x01) _delay_loop_(160);//延時等待
else _delay_loop_(72);//st7920要求等待72uS
}
/*--------------------------------------------------------
發送8位LCD顯示數據
--------------------------------------------------------*/
//__inline
void LcdObj::LcdSendData(unsigned char cData)
{
cData &= 0xff;
/*--------------------------------------------------------
發送同步脈沖11111 WR(0) RS(0) 0發送順序從左至右)
--------------------------------------------------------*/
#if (ccsdebug == 1)
McBSP1->SPSD |= (1 << PCR_FSXP);//IO模擬控制FSX信號=1
_delay_loop_(1);//延時等待
#endif
LcdSend(0xfa);//發送LCD顯示數據
LcdSend((cData & 0xf0) & 0xff);//發送高4位LCD顯示數據
LcdSend((cData << 4) & 0xff);//發送低4位LCD顯示數據
#if (ccsdebug == 1)
McBSP1->SPSD &= ~(1 << PCR_FSXP);//IO模擬控制FSX信號=0
#endif
_delay_loop_(72);//st7920要求等待延時72uS
}
//__inline
void LcdObj::SetLcdDisplayPos(unsigned int row, unsigned int col)
{
row &= 0x03;//LCD12864為4行漢字
col &= 0x0f;//每行8個漢字16個字符
LcdRow = row;
LcdCol = col;
LcdRowWriteEnable[row] = true;//允許此行刷新漢字顯示
}
//__inline
void LcdObj::LcdClearBuffer(void)
{
unsigned int i, j;
for (i = 0;i < 4;i ++) {
for (j = 0;j < 16; j ++) {
LcdBuffer[i][j] = ' ';
}
LcdRowWriteEnable[i] = true;//允許此行刷新漢字顯示
}
LcdRow = 0;
LcdCol = 0;
}
//__inline
void LcdObj::LcdDisplayBuffer(void)
{
unsigned int i, j;
for (i = 0; i < 4; i ++) {//LCD12864為4行漢字
if (LcdRowWriteEnable[i]) {//允許此行刷新漢字顯示
LcdSendCommand(0x80 + (i & 1) * 16 + (i >> 1) * 8);//移動光標
_delay_loop_(1);//延時等待
for (j = 0; j < 16; j ++) {//每行8個漢字16個字符
LcdSendData(LcdBuffer[i][j]);//刷新顯示字符
_delay_loop_(1);//延時等待
}
LcdRowWriteEnable[i] = false;//過后不允許此行刷新漢字顯示
_delay_loop_(1);//延時等待
}
}
}
//__inline
void LcdObj::LcdDisplay(const char * string)
{
while(*string) {
LcdBuffer[LcdRow][LcdCol ++] = (unsigned char)*string ++;
}
}
void LcdObj::LcdDisplay(unsigned char hexstr[], unsigned int len)
{
unsigned char ch;
for (int i = 0; i < len; i ++) {
ch = *hexstr++;
if (ch < 0xa0) {
LcdBuffer[LcdRow][LcdCol ++] = (ch >> 4) + '0';
}
else {
LcdBuffer[LcdRow][LcdCol ++] = (ch >> 4) - 10 + 'A';
}
if ((ch & 0x0f) < 0x0a) {
LcdBuffer[LcdRow][LcdCol ++] = (ch & 0x0f) + '0';
}
else {
LcdBuffer[LcdRow][LcdCol ++] = (ch & 0x0f) - 10 + 'A';
}
}
}
SystemObj Sys;
LcdObj Lcd;
int main(void)
{
Enable();//開中斷
while(1)
{
if (::IOXF) {
SREG->ST1 |= (1 << ST1_XF);
}
else {
SREG->ST1 &= ~(1 << ST1_XF);
}
idle();
}
}
interrupt void Timer0Isr() {
static int count = 0;
static int ledcount = 0;
char str[17];
count ++;
if (count >= 500) {
count = 0;
Lcd.SetLcdDisplayPos(0, 0);
std::sprintf(str, "ledcount=%04X ", ledcount >> 2);//注意std::
Lcd.LcdDisplay(str);
Lcd.LcdDisplayBuffer();//刷新LCD顯示緩沖區
Lcd.SetLcdDisplayPos(3, 0);
if ((ledcount & 0x03) == 0) {
Lcd.LcdDisplay("12345678");
Lcd.SetLcdDisplayPos(3, 8);
Lcd.LcdDisplay("我暈倒了");
}
else {
Lcd.LcdDisplay("你在倒塌");
Lcd.SetLcdDisplayPos(3, 8);
Lcd.LcdDisplay("87654321");
}
::IOXF = !::IOXF;//郁悶~~~中斷中ST1被保護~~~
ledcount ++;
}
}
interrupt void Timer1Isr() {//只運行1次
Lcd.SetLcdDisplayPos(1, 0);
Lcd.LcdDisplay("定時器一終于倒塌");
TIMER1->TCR |= (1 << TCR_TSS);//關閉啟動定時器1(自毀)
}
interrupt void Eint0Isr() {
Lcd.SetLcdDisplayPos(2, 0);
Lcd.LcdDisplay("歡迎INT0中斷觀光");
SREG->IFR = (1 << IFR_INT0);//清除INT0中斷標志
}
interrupt void Eint1Isr() {
Lcd.SetLcdDisplayPos(2, 0);
Lcd.LcdDisplay("歡迎INT1中斷觀光");
SREG->IFR = (1 << IFR_INT1);//清除INT1中斷標志
}
interrupt void Eint2Isr() {
Lcd.SetLcdDisplayPos(2, 0);
Lcd.LcdDisplay("歡迎INT2中斷觀光");
SREG->IFR = (1 << IFR_INT2);//清除INT2中斷標志
}
interrupt void Eint3Isr() {
Lcd.SetLcdDisplayPos(2, 0);
Lcd.LcdDisplay("歡迎INT3中斷觀光");
SREG->IFR = (1 << IFR_INT3);//清除INT3中斷標志
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -