播音提示器软件设计与实现
關(guān)鍵詞:液晶型提示器、鏡像、實(shí)時(shí)輸出、無(wú)線(xiàn)遙控器 、AVR單片機(jī)、串口、C語(yǔ)言、Visual C++、雙緩沖、延時(shí)函數(shù)、消息循環(huán)
前言:
????? 播音提示器是電視臺(tái)最常見(jiàn)的設(shè)備,其基本原理比較簡(jiǎn)單,即采用單反玻璃反射鏡像顯示的上滾文字。老式的提示器大多采用CRT顯示器和字幕上滾軟件,新型提示器大多使用液晶顯示屏輸出文字并使用了專(zhuān)用的實(shí)時(shí)播音提示軟件,部分型號(hào)還增加了遙控功能。
2007年10月隨著我臺(tái)真三維虛擬演播室的建設(shè),我們更新了一直使用老式DOS版字幕上滾軟件的播音提示器,即保留了單反玻璃、機(jī)架、用做輸出的21寸彩電,重新采購(gòu)了計(jì)算機(jī),重新設(shè)計(jì)編寫(xiě)了新的提示器軟件,設(shè)計(jì)制作了無(wú)線(xiàn)遙控電路和相關(guān)的單片機(jī)程序。
本文將詳細(xì)介紹提示器軟件的設(shè)計(jì)、無(wú)線(xiàn)遙控電路的設(shè)計(jì)以及相關(guān)的VC++程序、單片機(jī)C語(yǔ)言程序、電路原理圖。
提綱:
一、???????? 播音提示器的基本原理
二、???????? 使用VC++設(shè)計(jì)提示器軟件
三、???????? 實(shí)時(shí)高速貼圖的實(shí)現(xiàn)途徑----雙緩沖和消息循環(huán)
四、???????? 液晶顯示字幕與CRT顯示字幕的區(qū)別
五、???????? 使用無(wú)線(xiàn)遙控器,PT2262和PT2272
六、???????? 使用AVR單片機(jī)轉(zhuǎn)發(fā)信號(hào)
七、???????? 按鍵復(fù)用的問(wèn)題
八、???????? 提示器VC++程序主要源代碼
九、???????? AVR單片機(jī)CodeVision C語(yǔ)言源程序
十、???????? 結(jié)束語(yǔ)
正文:
一、???????? 播音提示器的基本原理
播音提示器利用單反玻璃單面反射和單面透射的光學(xué)特性,使播音員能夠看到擋在攝像機(jī)前面的單反玻璃上反射的上滾文字,而攝像機(jī)拍攝透過(guò)單反玻璃并不會(huì)受到另一面反射的文字的影響,播音提示器或通過(guò)攝像頭或通過(guò)計(jì)算機(jī)將文字顯示在于單反玻璃呈45度夾角的顯示器上,由于鏡面反射的緣故,要想看到反射形成的正像,顯示器必須輸出鏡像的畫(huà)面。鏡像畫(huà)面對(duì)于CRT顯示器來(lái)說(shuō)很簡(jiǎn)單,只需要拆開(kāi)機(jī)器交換行掃描輸出線(xiàn)即可,對(duì)于液晶顯示器來(lái)說(shuō)就沒(méi)有那么簡(jiǎn)單了,所有的鏡像畫(huà)面全部要通過(guò)計(jì)算機(jī)軟件來(lái)生成。至于鏡像的方法有兩種,一種是更改顯示輸出,使整個(gè)顯示畫(huà)面鏡像顯示,一種是通過(guò)實(shí)時(shí)運(yùn)算,鏡像一個(gè)貼圖區(qū),本文將介紹后一種實(shí)現(xiàn)方法。
二、??????? 使用VC++設(shè)計(jì)提示器軟件
很多字幕上滾軟件并不是實(shí)時(shí)貼圖的,即有一個(gè)生成上滾文件的過(guò)程。隨著計(jì)算機(jī)運(yùn)算能力的大幅躍升,采用優(yōu)化的算法、高效率的設(shè)計(jì)語(yǔ)言也是可以實(shí)現(xiàn)實(shí)時(shí)貼圖輸出的。VC++6.0是widows程序設(shè)計(jì)中應(yīng)用程序執(zhí)行效率較高的開(kāi)發(fā)平臺(tái)之一,而且其內(nèi)置的GDI繪圖函數(shù)可以很方便地輸出圖形,相比.net語(yǔ)言中的GDI+輸出速度上還有一定優(yōu)勢(shì)。
三、??????? 實(shí)時(shí)高速貼圖的實(shí)現(xiàn)途徑----雙緩沖和消息循環(huán)
在windows MFC程序設(shè)計(jì)中,即使是簡(jiǎn)單的刷新也可能使界面閃爍不已,要實(shí)現(xiàn)平滑流暢的文字滾動(dòng)效果依賴(lài)控件和定時(shí)器肯定是行不通的。我們只能通過(guò)雙緩沖的辦法,即在內(nèi)存中作圖,在貼圖的過(guò)程中又畫(huà)好下一幅圖片,如此反復(fù),在通過(guò)一定的延時(shí)手段,讓貼圖速度(文字滾動(dòng)速度)能夠得到很好的控制。
下面是一個(gè)使用液晶屏做為字幕輸出時(shí)鏡像貼圖的函數(shù),演示了內(nèi)存緩沖貼圖的技術(shù)。需要指出的是本文所采用的實(shí)時(shí)貼圖算法均衡考慮了一些實(shí)時(shí)參數(shù)修改響應(yīng)的問(wèn)題,并不是最精簡(jiǎn)的貼圖算法,實(shí)際上現(xiàn)在一般的計(jì)算機(jī)配置用這個(gè)函數(shù)也可以滾動(dòng)得飛快!
void CTishiqiDlg::Onplay2()
{
????? isPlayMirr=2;
????? //在內(nèi)存中建立位圖
????? CDC *pDC=GetDC();
????? CDC *pDCpic=m_pic.GetDC();
????? CDC dcMem;
//? BITMAP bm;
????? iExit=0;
????? CBitmap bmpBuf;
????? DWORD start,nowTime;?????
????? dcMem.CreateCompatibleDC(NULL);
????? bmpBuf.DeleteObject();
????? bmpBuf.CreateCompatibleBitmap(pDC,mWidth,mHeight);
????? CBitmap *poldBitmap=dcMem.SelectObject(&bmpBuf);
????? dcMem.SetBkMode(TRANSPARENT);
????? //輸出滾動(dòng)字幕
????? for (mTi=0;mTi<=mLen;mTi++)
????? {
??????? start=GetTickCount();
??????????
?????????? if (mLen<10)
?????????? {??? //估算文字長(zhǎng)度,如不考慮中途修改可去掉以提高速度
???????????????? CSize size=pDCpic->GetTextExtent(tStr);??
???????????????? int xx= size.cx;
???????????????? int? yy= size.cy;
???????????????? mLen=(xx/mWidth+1)*yy*172+mHeight;
????????????????
???????????????? pos=0;
?????????? }
?????????? rect.top=rect.top-m_slid2.GetPos();
?????????? pos=pos+m_slid2.GetPos();
????? //? m_slid3.SetScrollPos(pos,TRUE);
????? ??? if (iExit>0) mTi=mLen;
?????????? dcMem.SetTextColor(fontColor);
?????????? CFont *poldFont=dcMem.SelectObject(&m_font);
??????? dcMem.FillSolidRect(0,0,mWidth,mHeight,0);
?????????? dcMem.DrawText(tStr,rect,DT_WORDBREAK); //在內(nèi)存中輸出文字
?????????? pDCpic->StretchBlt(0,rect.bottom ,rect.right,-rect.bottom ,&dcMem, 0,0,rect.right,rect.bottom,SRCCOPY); //將內(nèi)存中的圖像鏡像旋轉(zhuǎn)并貼到m_pic圖片框
????? ???? DWORD dti=(DWORD)m_slid.GetPos();
????? ???? do??
??????? {??
???????????????? ?//消息循環(huán)
???????????????? ?MSG msg;
???????????????? ?PeekMessage(&msg,NULL,0,0,PM_REMOVE);
???????????????? ?TranslateMessage(&msg);
???????????????? ?DispatchMessage(&msg);
???????????????? nowTime=GetTickCount();
?????????? ?}while((nowTime-start)<dti);? //延時(shí)函數(shù)
????? }
??? dcMem.DeleteDC();
????? ReleaseDC(pDC);
????? ReleaseDC(pDCpic);
}
延時(shí)手段簡(jiǎn)單的說(shuō)有兩種,一種是使用定時(shí)器Timer,一種是通過(guò)GetTickCount()函數(shù)和循環(huán)來(lái)進(jìn)行ms級(jí)的延時(shí)。但是定時(shí)器的精度大約在20-30ms,因?yàn)檫€要執(zhí)行復(fù)雜的作圖操作通過(guò)定時(shí)器并不能滿(mǎn)足每秒25幀畫(huà)面的輸出要求;如果單純使用循環(huán)的話(huà),也不可行,因?yàn)?span lang="EN-US">Windows操作系統(tǒng)是通過(guò)消息來(lái)響應(yīng)各種操作的,循環(huán)操作會(huì)很顯著地將系統(tǒng)陷入一種無(wú)響應(yīng)的假死狀態(tài),所以還要在循環(huán)中加入消息循環(huán)機(jī)制,及時(shí)捕獲并將消息傳遞出去。
下面是一個(gè)采用了消息循環(huán)機(jī)制的延時(shí)模塊,這段程序和網(wǎng)上流行的延時(shí)程序不同,它避免了陷入等待消息輸入才能運(yùn)行的漏洞。
DWORD start,nowTime;??
for (;;;)
{??
start=GetTickCount();
//這里寫(xiě)你的代碼
do??
? {??
??? MSG msg;
??? PeekMessage(&msg,NULL,0,0,PM_REMOVE);
??? TranslateMessage(&msg);
??? DispatchMessage(&msg);
??? nowTime=GetTickCount();
? }while((nowTime-start)<dti);?
}
四、??????? 液晶顯示字幕與CRT顯示字幕的區(qū)別
前面提到液晶顯示器無(wú)法通過(guò)更改電路的方式來(lái)實(shí)現(xiàn)鏡像模式,只有通過(guò)軟件來(lái)實(shí)現(xiàn)。軟件實(shí)現(xiàn)包括驅(qū)動(dòng)層面的鏡像輸出和貼圖的鏡像輸出。前者會(huì)使整個(gè)操作界面都變成鏡像,很難再對(duì)軟件進(jìn)行操作,但在貼圖速度上有一定優(yōu)勢(shì);后一種方法只是文字上滾區(qū)域鏡像貼圖,而操控區(qū)域不變,有利于使用,但對(duì)計(jì)算機(jī)速度有一定要求。
Windows為我們提供了一個(gè)旋轉(zhuǎn)貼圖的函數(shù)StretchBlt(m_hDC, x, y, nWidth, nHeight,pSrcDC->GetSafeHdc(), xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop)通過(guò)設(shè)置不同參數(shù)可以很方便的鏡像圖像然后貼到特定的區(qū)域。我們可以使用這個(gè)函數(shù)實(shí)現(xiàn)液晶型提示器的顯示輸出(具體調(diào)用方法見(jiàn)第三節(jié)例程)。
五、??????? 使用無(wú)線(xiàn)遙控器,PT2262和PT2272
要播音員自主控制提示器可以使用筆記本電腦直接操作也可以使用遙控器,遙控器常見(jiàn)的有紅外遙控和無(wú)線(xiàn)遙控兩種,紅外遙控因發(fā)射距離短、紅外光不能被阻擋和發(fā)射紅外線(xiàn)時(shí)可以被攝像機(jī)拍到等缺陷不能采用,因此我們采用了無(wú)線(xiàn)遙控裝置。
常見(jiàn)的無(wú)線(xiàn)遙控器大多采用PT2262和PT2272發(fā)射接收芯片。PT2262/2272是臺(tái)灣普城公司生產(chǎn)的一種CMOS工藝制造的低功耗低價(jià)位通用編解碼電路,PT2262/2272最多可有12位(A0-A11)三態(tài)地址端管腳(懸空,接高電平,接低電平),任意組合可提供531441地址碼,PT2262最多可有6位(D0-D5)數(shù)據(jù)端管腳,設(shè)定的地址碼和數(shù)據(jù)碼從17腳串行輸出,可用于無(wú)線(xiàn)遙控發(fā)射電路。
我們采購(gòu)了一種有4個(gè)按鍵的PT2262遙控器和使用PT2272 M4芯片的接收模塊,無(wú)線(xiàn)遙控頻率為315MHz,PT2272 M4是不帶鎖存的接收芯片,對(duì)應(yīng)的PT2272 L4則帶鎖存。
PT2272 M4接收模塊有四個(gè)數(shù)據(jù)線(xiàn)分別為D10、D11、D12、D13以及解碼確認(rèn)端子VT和電源VCC、地GND等7個(gè)引腳。當(dāng)接收到地址編碼正確的遙控信號(hào)時(shí),VT輸出高電平,對(duì)應(yīng)的數(shù)據(jù)線(xiàn)也為高電平,無(wú)信號(hào)時(shí)均為低電平。
六、??????? 使用AVR單片機(jī)轉(zhuǎn)發(fā)信號(hào)
要使播音提示器軟件能夠響應(yīng)遙控操作,還需要能夠?qū)⑦b控信號(hào)(即接收模塊的VT電平變化、數(shù)據(jù)線(xiàn)電平變化)傳遞給計(jì)算機(jī),因此我們需要使用單片機(jī)來(lái)轉(zhuǎn)發(fā)這個(gè)信號(hào)。這里我們使用了ATMEL公司的AVR單片機(jī)AT MEGA8L,MEGA8L是一款低電壓8位單片機(jī)。通過(guò)MEGA8單片機(jī)可以采集到無(wú)線(xiàn)接收模塊的數(shù)據(jù)線(xiàn)和VT端口的電平變化,然后通過(guò)串行口轉(zhuǎn)發(fā)給計(jì)算機(jī),提示器軟件在得到串口接收數(shù)據(jù)的消息后立即調(diào)用相關(guān)函數(shù)響應(yīng)遙控操作。
單片機(jī)可以采用掃描端口的方法也可以將VT端接到單片機(jī)中斷輸入腳通過(guò)中斷來(lái)響應(yīng)遙控操作,我們?cè)谠O(shè)計(jì)電路時(shí)同時(shí)考慮了上述兩種處理方法,通過(guò)R13和R15(兩個(gè)只需焊接一個(gè)即可)來(lái)選擇。
七、??????? 按鍵復(fù)用的問(wèn)題
實(shí)際應(yīng)用中,僅有四個(gè)鍵(標(biāo)記為A、B、C、D)的遙控器并不能很好地滿(mǎn)足操作的需要,所以我們需要對(duì)按鍵進(jìn)行復(fù)用。按鍵的復(fù)用實(shí)際上在上位機(jī)軟件即提示器軟件中進(jìn)行處理。首先通過(guò)D鍵設(shè)置兩種操作狀態(tài),即滾動(dòng)狀態(tài)和調(diào)速狀態(tài),在滾動(dòng)狀態(tài)下,A、B鍵為前進(jìn)、后退鍵,可前進(jìn)或后退約半屏內(nèi)容,C鍵為開(kāi)始、暫停鍵,在調(diào)速狀態(tài)下,A、B為速度微調(diào)鍵,加減延時(shí)參數(shù)。
程序設(shè)置有自動(dòng)參數(shù)記憶功能,能夠在程序關(guān)閉時(shí)將現(xiàn)行參數(shù)記載下來(lái),下次啟動(dòng)時(shí)自動(dòng)調(diào)用。
八、???????? 提示器VC++程序主要源代碼:
軟件初始化部分
BOOL CTishiqiDlg::OnInitDialog()
{
????? CDialog::OnInitDialog();
????? // Add "About..." menu item to system menu.
????? // IDM_ABOUTBOX must be in the system command range.
????? ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
????? ASSERT(IDM_ABOUTBOX < 0xF000);
????? CMenu* pSysMenu = GetSystemMenu(FALSE);
????? if (pSysMenu != NULL)
????? {
?????????? CString strAboutMenu;
?????????? strAboutMenu.LoadString(IDS_ABOUTBOX);
?????????? if (!strAboutMenu.IsEmpty())
?????????? {
???????????????? pSysMenu->AppendMenu(MF_SEPARATOR);
???????????????? pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
?????????? }
????? }
????? // Set the icon for this dialog.? The framework does this automatically
????? //? when the application's main window is not a dialog
????? SetIcon(m_hIcon, TRUE);??????????????? // Set big icon
????? SetIcon(m_hIcon, FALSE);???????? // Set small icon
?????
????? mWidth=GetSystemMetrics(SM_CXSCREEN);
mHeight=GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(NULL,0,0,mWidth,mHeight-20 ,SWP_NOMOVE | SWP_NOZORDER); //調(diào)節(jié)程序自動(dòng)適應(yīng)桌面分辨率
????? mWidth=mWidth-70;
????? mHeight=mHeight-50;
????? rect.top=mHeight-100;
????? rect.bottom=mHeight;
????? rect.left=0;
????? rect.right=mWidth;
????? ResetParame();
????? //fontColor=RGB(255,255,0);
????? fontSize=720;
????? fontName="黑體?????????????????????????? ";
????? mLen=1;
????? m_font.CreatePointFont(fontSize,fontName,NULL);
????? Zmstr1="現(xiàn)在開(kāi)始調(diào)節(jié)滾動(dòng)速度,按遙控器 A 鍵速度加快,B 鍵速度減慢,D 鍵退回提示器模式!現(xiàn)在開(kāi)始調(diào)節(jié)滾動(dòng)速度,按遙控器 A 鍵速度加快,B 鍵速度減慢,D 鍵退回提示器模式!現(xiàn)在開(kāi)始調(diào)節(jié)滾動(dòng)速度,按遙控器 A 鍵速度加快,B 鍵速度減慢,D 鍵退回提示器模式!";
????? tStr="播音提示器";
????? m_slid.SetRangeMax(50,FALSE);
????? m_slid.SetRangeMin(0,FALSE);
????? m_slid.SetPos(Speed);
????? m_slid2.SetRangeMax(3,FALSE);
????? m_slid2.SetRangeMin(1,FALSE);
????? m_slid2.SetPos(Step);
????? isPlayMirr=0;
????? m_pic.SetWindowPos(NULL,0,0,mWidth,mHeight,SWP_NOMOVE | SWP_NOZORDER);
//? m_slid3.SetWindowPos(NULL,50,mHeight+10,mWidth+10,20, SWP_NOZORDER);
????? // TODO: Add extra initialization here
????? pos=0;
????? m_comm.SetPortOpen(TRUE);???????? //打開(kāi)串口
????? m_comm.SetSettings("9600,n,8,1");???? //串口參數(shù)設(shè)置??????
??? m_comm.SetInputMode(0);??????????? //設(shè)置TEXT緩沖區(qū)輸入方式??
??? iExit=2;
??? m_comm.SetRThreshold(1);???????
????? inBuffer.bstrVal=new unsigned short[100];
????? return TRUE;? // return TRUE? unless you set the focus to a control
}
字幕上滾程序(非鏡像模式)
void CTishiqiDlg::Onplay1()
{
????? // TODO: Add your control notification handler code here
????? isPlayMirr=1;
????? CDC *pDC=GetDC();
????? CDC *pDCpic=m_pic.GetDC();
????? CDC dcMem;
????? iExit=0;
????? CBitmap bmpBuf;
????? DWORD start,nowTime; ?????
????? dcMem.CreateCompatibleDC(NULL);
????? bmpBuf.DeleteObject();
????? bmpBuf.CreateCompatibleBitmap(pDC,mWidth,mHeight);
????? CBitmap *poldBitmap=dcMem.SelectObject(&bmpBuf);
????? dcMem.SetBkMode(TRANSPARENT);
????? for (mTi=0;mTi<=mLen;mTi++)
????? {
??????? start=GetTickCount();
?????????? if (mLen<10)
?????????? {
???????????????? CSize size=pDCpic->GetTextExtent(tStr);??
???????????????? int xx= size.cx;
???????????????? int? yy= size.cy;
???????????????? mLen=(xx/mWidth+1)*yy*172+mHeight;
???????????????? //m_slid3.SetScrollRange(0,mLen,TRUE);
???????????????? pos=0;
??????????
?????????? }
?????????? rect.top=rect.top-m_slid2.GetPos();
?????????? pos=pos+m_slid2.GetPos();
//??????? m_slid3.SetPos(pos);
????? ??? if (iExit>0) mTi=mLen;
?????????? dcMem.SetTextColor(fontColor);
?????????? CFont *poldFont=dcMem.SelectObject(&m_font);
??????? dcMem.FillSolidRect(0,0,mWidth,mHeight,0);
?????????? dcMem.DrawText(tStr,rect,DT_WORDBREAK);
?????????? pDCpic->StretchBlt(0,0 ,rect.right,rect.bottom ,&dcMem, 0,0,rect.right,rect.bottom,SRCCOPY);?? //? 和鏡像模式有區(qū)別
????? ??? DWORD dti=(DWORD)m_slid.GetPos();
????? ??? do??
??????? {??
???????????????? ?MSG msg;
???????????????? ?PeekMessage(&msg,NULL,0,0,PM_REMOVE);
???????????????? ?TranslateMessage(&msg);
???????????????? ?DispatchMessage(&msg);
???????????????? ?nowTime=GetTickCount();
?????????? }while((nowTime-start)<dti);?
????? }
??? dcMem.DeleteDC();
????? ReleaseDC(pDC);
????? ReleaseDC(pDCpic);
}
串口消息響應(yīng)程序
void CTishiqiDlg::OnOnCommMscomm1()
{
????? // TODO: Add your control notification handler code here
????? if (m_comm.GetCommEvent()==2)
????? {???
?????????? inBuffer=m_comm.GetInput();
?????????? CString strx;
?????????? int i;
?????????? strx=_T(inBuffer.bstrVal);
?????????? if (strx=="a") i=4;
?????????? if (strx=="b") i=3;
?????????? if (strx=="c") i=2;
?????????? if (strx=="d") i=1;
?????????? switch(i)
?????????? {???
?????????? case 1:
???????????????? {
????????????????????? if (iExit==0) rect.top=rect.top-100;
????????????????????? if (iExit==1)
????????????????????? {
??????????????????????????? rect.top=rect.top-100;
??????????????????????????? ShowTxt();
??????????????????????????? //OnPause();
????????????????????? }
????????????????????? if (iExit==3) m_slid.SetPos(m_slid.GetPos()-2);
????????????????????? break;
???????????????? }
?????????? case 2:
???????????????? {
????????????????????? if (iExit==0)
????????????????????? {
??????????????????????????? rect.top=rect.top+100;
???????????????????????????
????????????????????? }
????????????????????? if (iExit==1)
????????????????????? {
??????????????????????????? rect.top=rect.top+100;
??????????????????????????? ShowTxt();
?????????????????????
????????????????????? }
????????????????????? if (iExit==3) m_slid.SetPos(m_slid.GetPos()+2);
????????????????????? break;
???????????????? }
?????????? case 3:
???????????????? {
????????????????????? if (iExit==2)
????????????????????? {
??????????????????????????? Onplay1();
????????????????????? }
????????????????????? OnPause();
?????????????????????
????????????????????? break;
???????????????? }
?????????? case 4:
???????????????? {
????? ???????????????? if (iExit==3)
????????????????????? {
??????????????????????????? OnStop();
??????????????????????????? Onplay1();
??????????????????????????? OnStop();
????????????????????? }
????????????????????? if (iExit==2) TestSpeed();
????????????????????? if (iExit<2)?
????????????????????? {
??????????????????????????? OnStop();
??????????????????????????? iExit=2;
????????????????????? }
????????????????????? break;
???????????????? }
?????????? }
????? }
}
九、??????? AVR單片機(jī)CodeVision C語(yǔ)言源程序:
下面是使用CodeVision編譯器編寫(xiě)的AVR單片機(jī)C語(yǔ)言程序,采用掃描端口的方式獲取遙控信息,并通過(guò)串行口將遙控按鍵以字符”a”、”b”、”c”、”d”簡(jiǎn)單地轉(zhuǎn)發(fā)給計(jì)算機(jī)。實(shí)際上我們還可以寫(xiě)入一個(gè)加密算法,同時(shí)將其作為一個(gè)加密狗來(lái)使用。
/*****************************************************
Chip type?????????? : ATmega8L
Program type??????? : Application
Clock frequency???? : 4.000000 MHz
Memory model??? ????: Small
External SRAM size? : 0
Data Stack size???? : 256
*****************************************************/
#include <mega8.h>
// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>
char cc;
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=1
PORTB=0x01;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normaltop=FFFFh
// OC1Aoutput: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normaltop=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
while (1)
????? {
????? cc=PINC;
????? if (PINC.4==1)
????? { ????
??????????
?????????????? //? putchar('r');
????????????????????? //掃描端口并轉(zhuǎn)發(fā)信息
??????????????? //PORTB.0=~PORTB.0;
??????????????? if (PINC.0==1)? putchar('d');
??????????????? if (PINC.1==1)? putchar('c');
??????????????? if (PINC.2==1)? putchar('b');
??????????????? if (PINC.3==1)? putchar('a');
??????????????? //delay_ms(10);
??????????????? //PORTB.0=~PORTB.0;
???????????????
??????????????? while (PINC.4==1)
??????????????? {??????
??????????????????????? PORTB.0=~PORTB.0;//發(fā)光二極管閃爍
??????????????????????? delay_ms(20);
???????
???????????????? }
??????????????? PORTB.0=1;//發(fā)光二極管滅
??????? }
????? };
}
總結(jié)
以上是生活随笔為你收集整理的播音提示器软件设计与实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python读取rtf文件_【Pytho
- 下一篇: 学校计算机教室报损登记本,学校设施设备管