? ? ? ??《嵌入式系統(tǒng)開發(fā)》系列專欄主要以LPC1100系列微控制器為硬件平臺,詳細(xì)介紹Cortex—-M0微控制器的原理與開發(fā)技術(shù),基于keil仿真軟件平臺設(shè)計(jì)最小應(yīng)用系統(tǒng)板和具有在板仿真器的口袋開發(fā)板以及相關(guān)例程。
? ? ? ??本文已收錄于嵌入式系統(tǒng)開發(fā)系列專欄:嵌入式系統(tǒng)開發(fā) 歡迎訂閱,持續(xù)更新。文章來源地址http://www.zghlxwxcb.cn/news/detail-715349.html
【嵌入式系統(tǒng)開發(fā)】Keil 實(shí)現(xiàn)十次作業(yè)詳細(xì)代碼目錄
作業(yè)1 利用delay()函數(shù)實(shí)現(xiàn)led閃爍
作業(yè)2:利用系統(tǒng)節(jié)拍定時(shí)器實(shí)現(xiàn)LED燈閃爍
作業(yè)3 按鍵輸入控制LED燈閃爍頻率
作業(yè)4 設(shè)置16位定時(shí)器1工作在PWM模式
作業(yè)5 UART數(shù)據(jù)傳輸
作業(yè)6:LM75BD溫度檢測
作業(yè)7FLASH存儲器操作
作業(yè)8 ADC模數(shù)轉(zhuǎn)換
作業(yè)9? 電源管理與功率控制
作業(yè)10:RTC時(shí)間設(shè)置與讀取
作業(yè)1 利用delay()函數(shù)實(shí)現(xiàn)led閃爍
實(shí)現(xiàn)兩秒亮滅
#include "LPC11xx.h" // 引入LPC11xx芯片的頭文件,該文件中定義了LPC11xx的寄存
void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); // 使能GPIO的時(shí)鐘,將GPIO所在的AHB總線時(shí)鐘位設(shè)置為1
LPC_GPIO1->DIR |= (1UL << 9); // 配置GPIO1.9為輸出引腳
}
void LED_On(void) {
LPC_GPIO1->DATA &= ~(1UL << 9); // 設(shè)置GPIO1.9輸出低電平,點(diǎn)亮LED
}
void LED_Off(void) {
LPC_GPIO1->DATA |= (1UL << 9); // 設(shè)置GPIO1.9輸出高電平,熄滅LED
}
void Delay_1s(void){
int i=SystemCoreClock/5; // 計(jì)算循環(huán)次數(shù),延時(shí)1秒
while(--i); // 進(jìn)行延時(shí)
}
int main (void) {
LED_Init(); // 初始化LED
while (1) {
LED_On(); // 點(diǎn)亮LED
Delay_1s(); // 延時(shí)1秒
LED_Off(); // 熄滅LED
Delay_1s(); // 延時(shí)1秒
}
return 0;
}
作業(yè)2:利用系統(tǒng)節(jié)拍定時(shí)器實(shí)現(xiàn)LED燈閃爍
通過系統(tǒng)節(jié)拍定時(shí)器,中斷服務(wù)子程序,完成小燈不停的閃爍(亮滅),閃爍間隔3秒,并為每一行代碼寫漢語注釋
#include "LPC11xx.h" /* 引入頭文件"LPC11xx.h" */
extern volatile unsigned char clock_1s; /*外部變量聲明 */
/*系統(tǒng)節(jié)拍定時(shí)器中斷處理函數(shù)*/
void SysTick_Handler (void) {
static unsigned long ticks; /* 靜態(tài)無符號長整型變量聲明*/
if (ticks++ >= 149) { /*定時(shí)10ms,循環(huán)150次 */
ticks = 0; /*初始化賦值變量 ticks */
clock_1s = 1; /*設(shè)置標(biāo)志 */
}
} /*中斷設(shè)置,按照節(jié)拍定時(shí)器所給的時(shí)間進(jìn)行中斷,我們給定10ms執(zhí)行一次,實(shí)現(xiàn)LED閃爍間隔3s */
/* LED初始化設(shè)置 */
void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); /* GPIO 時(shí)鐘使能 */
LPC_GPIO1->DIR |= (1UL << 9); /*將 GPIO1_9 作為輸出口*/
}
/*狀態(tài)翻轉(zhuǎn)函數(shù),使用一次后,燈的狀態(tài)翻轉(zhuǎn)一次 */
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL <<9); /* LED 閃爍切換 */
}
/*主函數(shù)*/
int main (void) { /* 主程序開始 */
SysTick_Config(SystemCoreClock/100); /* 定時(shí)器10ms定時(shí)一次 */
LED_Init(); /* LED 初始化 */
while (1) { /* 無限循環(huán),以實(shí)現(xiàn)小燈的不停閃爍 */
if(clock_1s){ /* clock_1s = 1時(shí),中斷執(zhí)行結(jié)束 */
clock_1s = 0; /*標(biāo)志*/
LED_Toggle(); /* 執(zhí)行LED狀態(tài)翻轉(zhuǎn)函數(shù) */
}
}
}
作業(yè)3 按鍵輸入控制LED燈閃爍頻率
在Keil MDK 4.74上編寫一段程序,系統(tǒng)上電,系統(tǒng)工作頻率為48MHz,RGB紅色燈亮,利用系統(tǒng)節(jié)拍定時(shí)器SysTick實(shí)現(xiàn)定時(shí)1s,控制LPC1114微控制器的GPIO引腳PIO1_9狀態(tài)反轉(zhuǎn)(LED燈BLINKY閃爍),設(shè)置按鍵PIO0_1,PIO1_4,PIO1_8,為GPIO輸入,設(shè)置中斷方式判斷按鍵狀態(tài)。
按鍵功能:1. PIO1_4按鍵按下增加定時(shí)時(shí)間,最大2s,PIO1_8按鍵按下減少定時(shí)時(shí)間,最小100ms,步進(jìn)間隔100ms,適當(dāng)考慮按鍵防抖功能。2. 按鍵PIO0_1按下,降低系統(tǒng)工作頻率為24MHz,RGB綠色燈亮,觀察一下LED燈BLINKY閃爍的頻率有無變化?分析原因;再次按下,系統(tǒng)工作頻率恢復(fù)到48MHz,RGB紅色燈亮,觀察LED燈BLINKY閃爍的頻率。
#include "LPC11xx.h" /* LPC11xx definitions */
/* Followling definitions are associated with function */
#define CLOCK_SETUP 1
#define SYSOSCCTRL_Val 0x00000000 // Reset: 0x000
#define WDTOSCCTRL_Val 0x00000000 // Reset: 0x000
#define SYSPLLCTRL_Val 0x00000023 // Reset: 0x000
#define SYSPLLCTRL24_Val 0x00000041 // M=2,P=4
#define SYSPLLCLKSEL_Val 0x00000001 // Reset: 0x000
#define MAINCLKSEL_Val 0x00000003 // Reset: 0x000
#define SYSAHBCLKDIV_Val 0x00000001 // Reset: 0x001
volatile unsigned char clock_1s; /* Blink symble when 1 to blink */
uint32_t d=10;
uint8_tb=1; /* Frequency symble when 1 is 48MHz*/
uint32_ts=999; /* The interrupt cycles */
/*----------------------------------------------------------------------------
The Subfunction
*----------------------------------------------------------------------------*/
void LED_Init(void) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); /*enable clock for GPIO*/
LPC_GPIO1->DIR |= (1UL << 9); /*configure GPIO1_9 as output*/
LPC_GPIO2->DIR |= (1UL << 9);/*configure GPIO2_9 as output*/
LPC_GPIO2->DIR |= (1UL << 8);/*configure GPIO2_8 as output*/
LPC_GPIO2->DATA &= ~(1UL <<9);/*turn on red1_9*/
LPC_GPIO2->DATA |= (1UL << 8);/*turn off green1_8*/
}
void Key_Init(void){
LPC_GPIO0->DIR &=~(1UL<<1); /*configure GPIO0_1 as input*/
LPC_GPIO1->DIR &=~(1UL<<4); /*configure GPIO1_4 as intput*/
LPC_GPIO1->DIR &=~(1UL<<8); /*configure GPIO1_8 as intput*/
LPC_IOCON->PIO0_1 &= ~0x07;
LPC_IOCON->PIO0_1 |= 0x00; /*configure PIO0_1 as GPIO*/
LPC_IOCON->PIO1_4 &= ~0x07;
LPC_IOCON->PIO1_4 |= 0x00;/*configure PIO1_4 as GPIO*/
LPC_IOCON->PIO1_8 &= ~0x07;
LPC_IOCON->PIO1_8 |= 0x00;/*configure PIO1_8 as GPIO*/
LPC_GPIO0->IEV &=~(1UL<<1); /*falling edge trigger*/
LPC_GPIO0->IE |=(1UL<<1); /*Open GPIO0_1 interrupt function*/
LPC_GPIO1->IEV &=~(1UL<<4); /*falling edge trigger*/
LPC_GPIO1->IE |=(1UL<<4); /*Open GPIO1_4 interrupt function*/
LPC_GPIO1->IEV &=~(1UL<<8); /*falling edge trigger*/
LPC_GPIO1->IE |=(1UL<<8); /*Open GPIO1_8 interrupt function*/
NVIC_EnableIRQ(EINT0_IRQn); /*Use CMSIS P0 inner function*/
NVIC_EnableIRQ(EINT1_IRQn); /*Use CMSIS P1 inner function*/
}
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL <<9); /* Toggle the BLINKY LED */
}
void SystemInit24 (void) { /* Change the system frequency to 24MHz */
volatile uint32_t i;
#if (CLOCK_SETUP) /* Clock Setup */
#if ((SYSPLLCLKSEL_Val & 0x03) == 1)
LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */
LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val;
for (i = 0; i < 200; i++) __NOP();
#endif
LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */
LPC_SYSCON->SYSPLLCLKUEN= 0x01; /* Update Clock Source */
LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */
LPC_SYSCON->SYSPLLCLKUEN = 0x01;
while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */
#if ((MAINCLKSEL_Val & 0x03) == 3) /* Main Clock is PLL Out */
LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL24_Val; /* SYSPLLCTRL24_Val 0x00000041 0100 0001 M=2,10 P=4*/
LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */
while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */
#endif
#if (((MAINCLKSEL_Val & 0x03) == 2) )
LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val;
LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */
for (i = 0; i < 200; i++) __NOP();
#endif
LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */
LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
LPC_SYSCON->MAINCLKUEN = 0x01;
while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */
LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val;
#endif
}
void SysTick_Handler(void){
static unsigned long ticks;
if(ticks++ >=s){ /*Set Clocks to 1 every (s+1)ms*/
ticks = 0;
clock_1s = 1
}
void CutShiver(uint32_t t) /* Eliminate the key jitter */
{while(t--) ;
}
void PIOINT0_IRQHandler(void){ /* The interrupt tiggering event of P0 */
if((LPC_GPIO0->DATA&(1<<1))==0) /* Determine whether GPIO0_1 is pressed */
{
CutShiver(0xff); /* Eliminate the key jitter */
if((LPC_GPIO0->DATA&(1<<1))==0) /* Prevent misjudgment */
{
while((LPC_GPIO0->DATA&(1<<1))==0); /*waiting for release key*/
if(b==1) /* Determine the current system frequency */
{LPC_GPIO2->DATA |= (1UL <<9); /*turn off red*/
LPC_GPIO2->DATA &= ~ (1UL <<8); /*turn on green*/
SystemInit24(); /* Change the system frequency to 24MHz */
SystemCoreClockUpdate(); /* Update the core clock */
b=0; /* Change the frequency symble */
LPC_GPIO0->IC |=(1<<1); /*Clear the interrupt*/
}
lse
{
LPC_GPIO2->DATA|= (1UL <<8); /*turn off green*/
LPC_GPIO2->DATA &= ~(1UL <<9); /*turn on red*/
SystemInit(); /* Change the system frequency to 48MHz */
SystemCoreClockUpdate(); /* Update the core clock */
b=1; /* Change the frequency symble */
LPC_GPIO0->IC |=(1<<1); /*Clear the interrupt*/
}
}
}
}
void PIOINT1_IRQHandler(void){ /* The interrupt tiggering event of P1 */
if((LPC_GPIO1->DATA&(1<<4))!=(1<<4)) /* Determine whether GPIO1_4 is pressed */
{ CutShiver(0xff); /* Eliminate the key jitter */
if((LPC_GPIO1->DATA&(1<<4))!=(1<<4)) /* Prevent misjudgment */
{while((LPC_GPIO1->DATA&(1<<4))==0); /*waiting for release key*/
if(d<20)
d=d+1;
s=d*100-1; /* Add 100ms to the delay */
LPC_GPIO1->IC |= (1<<4); /*Clear the interrupt*/
}
}
else if((LPC_GPIO1->DATA&(1<<8))!=(1<<8)) /* Determine whether GPIO1_8 is pressed */
{CutShiver(0xff);/* Eliminate the key jitter */
if((LPC_GPIO1->DATA&(1<<8))!=(1<<8)) /* Prevent misjudgment */
{while((LPC_GPIO1->DATA&(1<<8))==0); /*waiting for release key*/
if(d>1)
d=d-1;
s=d*100-1; /* Reduce 100ms to the delay */
LPC_GPIO1->IC |= (1<<8); /*Clear the interrupt*/
}
}
}
/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void) { /* Main Program */
LED_Init(); /*LED gpio init*/
Key_Init();/*KEY gpio init*/
SystemInit(); /*Init system frequence to the 48MHz*/
SysTick_Config(SystemCoreClock/1000); /*Generate an interruption every 1ms*/
while(1){
if(clock_1s)
{clock_1s=0;/* Reload the blink symble */
LED_Toggle(); /* Toggle the BLINKY LED */
}
}
}
作業(yè)4 設(shè)置16位定時(shí)器1工作在PWM模式
(1)利用16位定時(shí)器1實(shí)現(xiàn)定時(shí)1s,控制LPC1114微控制器的GPIO引腳PIO1_9上的LED燈狀態(tài)反轉(zhuǎn)(可以用中斷方式也可以用匹配輸出功能);
(2)利用另外一個(gè)定時(shí)器定時(shí)增大或者減小占空比,實(shí)現(xiàn)PIO1_9上的LED燈漸亮漸滅的呼吸燈效果,改變呼吸的頻率觀察效果。
//第一題
#include "lpc11xx.h" // 包含LPC11xx的頭文件
void LED_init(void) // LED初始化函數(shù)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); // 使能GPIO的時(shí)鐘
LPC_GPIO1->DIR |= (1UL << 9); // GPIO1.9設(shè)置為輸出模式
LPC_GPIO1->DATA &= ~(1UL << 9); // GPIO1.9輸出低電平
}
void LED_Toggle(void) // LED閃爍函數(shù)
{
LPC_GPIO1->DATA ^= (1UL << 9); // 取反GPIO1.9的輸出電平
}
void TMR16B1_COUNT_Init(void) // 16位定時(shí)器初始化函數(shù)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8); // 使能定時(shí)器的時(shí)鐘
LPC_TMR16B1->IR = 0x1F; // 定時(shí)器中斷標(biāo)志寄存器清零
LPC_TMR16B1->PR = 999; // 定時(shí)器分頻系數(shù)為1000
LPC_TMR16B1->MCR = 3; // 匹配后TC復(fù)位并中斷
LPC_TMR16B1->MR0 = SystemCoreClock / 1000; // 定時(shí)器的匹配寄存器設(shè)為1ms
LPC_TMR16B1->TCR = 0x01; // 使能定時(shí)器
NVIC_EnableIRQ(TIMER_16_1_IRQn); // 使能定時(shí)器中斷
}
void TIMER16_1_IRQHandler(void) // 定時(shí)器中斷處理函數(shù)
{
if ((LPC_TMR16B1->IR |= 0x01) == 1) // 判斷是否為定時(shí)器匹配中斷
LED_Toggle(); // LED閃爍
}
int main() // 主函數(shù)
{
LED_init(); // 調(diào)用LED初始化函數(shù)
TMR16B1_COUNT_Init(); // 調(diào)用定時(shí)器初始化函數(shù)
while(1); // 一直循環(huán)
return 0; // 返回0
}
//第二題
#include "lpc11xx.h"
int flag=1; //flag 加減標(biāo)志
float x=0; //占空比
void LED_init(void) //LED initial
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6); /* enable clock for GPIO */
/* configure GPIO1.9 as output */
LPC_GPIO1->DIR |= (1UL << 9);
//PC_GPIO1->DATA &= ~(1UL << 9);
}
void TMR16B1_PWM_Init(void) /*16位定時(shí)器1初始化*/
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 8);//16位定時(shí)器1使能
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 16);//開啟時(shí)鐘
LPC_IOCON->PIO1_9 |= 0x01; //P1_9復(fù)用為mat0
LPC_TMR16B1->PR = 0; //分頻1
LPC_TMR16B1->PWMC= 0x01; //MAT0為PWM模式
LPC_TMR16B1->MCR = 0x02 <<9; //匹配后TC復(fù)位且不中斷
LPC_TMR16B1->MR3 = SystemCoreClock/1000; //MR3 1ms通道3計(jì)時(shí)
LPC_TMR16B1->MR0 = LPC_TMR16B1->MR3;//輸出
LPC_TMR16B1->TCR = 0x01; //使能定時(shí)器1
}
void TMR32B0_Init(void){ /*32位定時(shí)器0初始化*/
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<9); //使能
LPC_TMR32B0->IR=0x1F; //中斷清0
LPC_TMR32B0->PR=0; //分頻1
LPC_TMR32B0->MCR=3; //匹配后復(fù)位TC并中斷
LPC_TMR32B0->MR0=SystemCoreClock/10; //中斷時(shí)間0.1s
LPC_TMR32B0->TCR=0x01; //使能定時(shí)器
NVIC_EnableIRQ(TIMER_32_0_IRQn); //設(shè)置中斷并使能
}
void TIMER32_0_IRQHandler(void){ //中斷子程序
if((LPC_TMR32B0->IR|=0x01)==1){ //判斷MR0是否中斷并清零中斷
if(x<=0.13) //周期改變占空比x<0.13則不斷增加占空比,到達(dá)0.92后不斷減少
flag=1;
else if(x>=0.92)
flag=0;
if(flag==1) //經(jīng)過不斷實(shí)驗(yàn)調(diào)試發(fā)現(xiàn)此數(shù)值能得到較好的呼吸燈結(jié)果
x=x+0.05;
else if(flag==0)
x=x-0.05;
}
}
int main()
{
LED_init();
TMR32B0_Init();
TMR16B1_PWM_Init();
while(1)
{
LPC_TMR16B1->MR0 = x*LPC_TMR16B1->MR3; //不同占空比輸出
}
}
作業(yè)5 UART數(shù)據(jù)傳輸
(1)初始化LPC1114微控制器UART串行口,設(shè)置波特率為115200,數(shù)據(jù)位:8,停止位:1;校驗(yàn)位:無;中斷使能;
(2)利用中斷方式等待接收數(shù)據(jù),利用PC串口調(diào)試助手向LPC1114發(fā)送一個(gè)16進(jìn)制數(shù)據(jù)0xAA,LPC1114接收到數(shù)據(jù)后,發(fā)送一個(gè)十六進(jìn)制數(shù)據(jù)0x55,串口調(diào)試助手應(yīng)該能夠正確顯示接收到的數(shù)據(jù)。
(3)嘗試使用FIFO連續(xù)發(fā)送和接收一組數(shù)據(jù)(不超過16字節(jié))。
第一題程序
#include "LPC11xx.h" /* LPC11xx definitions */
int i=0;
uint8_t test=0x55;//發(fā)送數(shù)據(jù)
char wro[5]="error";//若輸入其他則返回錯(cuò)誤
uint8_t data[8];//接收緩沖區(qū)
void UART_init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL|=((1UL<<6)|(1UL<<16));//使能IOCON時(shí)鐘:SYSAHBCLKCTRL寄存器的16位為IO配置塊時(shí)鐘使能位
LPC_IOCON->PIO1_6=(1UL<<0);//IOCON->PIO1_6寄存器的2:0位為001則將P1.6設(shè)置為RXD
LPC_IOCON->PIO1_7=(1UL<<0); //IOCON->PIO1_7寄存器的2:0位為001則將P1.7設(shè)置為TXD
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<12);//使能UART時(shí)鐘
LPC_SYSCON->UARTCLKDIV=(4UL<<0);//時(shí)鐘分頻值為4:,則時(shí)鐘為12MHZ 波特率=【12000000/(16*4)】*【8/(8+5)】=11538
LPC_UART->LCR=0x83;//UART線控制寄存器,0x83對應(yīng)10000011 故8位傳輸,1個(gè)停止位,無奇偶校驗(yàn),使能對除數(shù)鎖存器的訪問
LPC_UART->DLL=4;//寫除數(shù)鎖存器低位值
LPC_UART->FDR=0x85;//1000 0101 8,5 FR=0.615
LPC_UART->DLM=0;//寫除數(shù)鎖存器高位值,如果該寄存器前四位>0且DLM=0,則DLL寄存器的值必須大于等于3
LPC_UART->LCR=0x03;//禁止對除數(shù)鎖存器訪問,即00000011,DLAB=0
LPC_UART->IER=0x01;//設(shè)置UART中斷使能寄存器
LPC_UART->FCR=0x81;//使能FIFO 收滿1字節(jié)中斷
NVIC_EnableIRQ(UART_IRQn);//使能UART中斷
}
void UART_SendBytes(void) //發(fā)送數(shù)據(jù)
{
int a;
if(data[0]==0xAA){ //如果是AA則發(fā)送55
LPC_UART->THR=test; //測試數(shù)據(jù)可更改
}
else{
for(a=4;a>0;a--){//如果不是AA則發(fā)送error
LPC_UART->THR=wro[a];
}
while((LPC_UART->LSR&0x40)==0);//等待發(fā)送完畢
}
void UART_IRQHandler(void)
{
if(i==8) i=0;
switch(LPC_UART->IIR&0x0f)
{
case 0x04: //RDA
for(;i<8;i++){
data[1]=LPC_UART->RBR;//讀取數(shù)據(jù)保存到data中
}
UART_SendBytes();
break;
case 0x0c: //CTI
while((LPC_UART->LSR&0x01)==1){
data[i++]=LPC_UART->RBR;//讀取數(shù)據(jù)
}
UART_SendBytes();
break;
default:
break;
}
}
/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void) { /* Main Program */
UART_init();
while(1);
}
第二題程序
#include"lpc11xx.h"
int i=0;
int sen=0;
int rec=0;
uint16_t sendbuf[8];
uint16_t recvbuf[8];
void UART_init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL|=((1UL<<6)|(1UL<<16));//使能IOCON時(shí)鐘:SYSAHBCLKCTRL寄存器的16位為IO配置塊時(shí)鐘使能位
LPC_IOCON->PIO1_6=(1UL<<0);//IOCON->PIO1_6寄存器的2:0位為001則將P1.6設(shè)置為RXD
LPC_IOCON->PIO1_7=(1UL<<0); //IOCON->PIO1_7寄存器的2:0位為001則將P1.7設(shè)置為TXD
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<12);//使能UART時(shí)鐘
LPC_SYSCON->UARTCLKDIV=(4UL<<0);//時(shí)鐘分頻值為4:,則時(shí)鐘為12MHZ 波特率=【12000000/(16*4)】*【8/(8+5)】=11538
LPC_UART->LCR=0x83;//UART線控制寄存器,0x83對應(yīng)10000011 故8位傳輸,1個(gè)停止位,無奇偶校驗(yàn),使能對除數(shù)鎖存器的訪問
LPC_UART->DLL=4;//寫除數(shù)鎖存器低位值
LPC_UART->FDR=0x85;//1000 0101 8,5 FR=0.615
LPC_UART->DLM=0;//寫除數(shù)鎖存器高位值,如果該寄存器前四位>0且DLM=0,則DLL寄存器的值必須大于等于3
LPC_UART->LCR=0x03;//禁止對除數(shù)鎖存器訪問,即00000011,DLAB=0
LPC_UART->IER=0x01;//設(shè)置UART中斷使能寄存器
LPC_UART->FCR=0x81;//使能FIFO 收滿1字節(jié)中斷
NVIC_EnableIRQ(UART_IRQn);//使能UART中斷
}
void UART_SendBytes(void)//發(fā)送數(shù)據(jù)
{
for(rec=0;rec<8;rec++)
{
sendbuf[rec]=recvbuf[rec]; //把接受數(shù)據(jù)存到發(fā)送數(shù)據(jù)數(shù)組
}
for(sen=0;sen<8;sen++){ //依次發(fā)送
LPC_UART->THR=sendbuf[sen];
while((LPC_UART->LSR&0x40)==0); //等待發(fā)送完畢
}
}
void UART_IRQHandler(void)
{switch(LPC_UART->IIR&0x0f)
{
case 0x04: //發(fā)生RDA中斷
recvbuf[i++]=LPC_UART->RBR; // 從RBR讀取數(shù)據(jù)
if(i==8) {
UART_SendBytes();
i=0;
}
break;
case 0x0c: //發(fā)生字符超時(shí)中斷
while((LPC_UART->LSR&0x01)==1){
recvbuf[i++]=LPC_UART->RBR; //從RBR讀取數(shù)據(jù)
}
if(i==8) {
UART_SendBytes(); //收集滿8個(gè)字符則發(fā)送
i=0;
}
break;
default:
break;
}
}
/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void) { /* Main Program */
UART_init();
while(1);
}
作業(yè)6:LM75BD溫度檢測
(1)初始化LPC1114微控制器UART串行口,定時(shí)器和I2C總線接口;
(2)利用通用定時(shí)器實(shí)現(xiàn)定時(shí)1s中斷,在定時(shí)器中斷服務(wù)子程序中讀取LM75BD(I2C總線)當(dāng)前溫度值,并通過串行口發(fā)送到PC,在PC上利用串口調(diào)試助手接收數(shù)據(jù),并觀察溫度的變化。
#include "lpc11xx.h"
/* I2C 控制寄存器 */
#define I2CONSET_AA (1<<2) // 是否產(chǎn)生應(yīng)答信號允許位,即是否設(shè)置為從機(jī)模式
#define I2CONSET_SI (1<<3) // I2C中斷標(biāo)志位
#define I2CONSET_STO (1<<4) // 停止標(biāo)志位
#define I2CONSET_STA (1<<5) // 開始標(biāo)志位
#define I2CONSET_I2EN (1<<6) // I2C接口允許位
/* I2C “清控制寄存器位”寄存器 */
#define I2CONCLR_AAC (1<<2) // 清應(yīng)答信號允許位
#define I2CONCLR_SIC (1<<3) // 清I2C中斷標(biāo)志位
#define I2CONCLR_STAC (1<<5) // 清開始標(biāo)志位
#define I2CONCLR_I2ENC (1<<6) // 清I2C接口允許位
void TMR32B0_Init(void){ /*32位定時(shí)器0初始化*/
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<9); //使能
LPC_TMR32B0->IR=0x1F; //中斷清0
LPC_TMR32B0->PR=9; //分頻9 9+1=10,1s
LPC_TMR32B0->MCR=3; //匹配后復(fù)位TC并中斷
LPC_TMR32B0->MR0=SystemCoreClock/10; //中斷時(shí)間0.1s
LPC_TMR32B0->TCR=0x01; //使能定時(shí)器
NVIC_EnableIRQ(TIMER_32_0_IRQn); //設(shè)置中斷并使能
}
void UART_init(uint32_t baudrate)
{
uint32_t DL_value,Clear=Clear; // (用這種方式定義變量解決編譯器的Warning)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘
LPC_IOCON->PIO1_6 &= ~0x07;
LPC_IOCON->PIO1_6 |= 0x01; //把P1.6腳設(shè)置為RXD
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01; //把P1.7腳設(shè)置為TXD
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘
LPC_SYSCON->UARTCLKDIV = 0x1; //時(shí)鐘分頻值為1
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); //允許UART時(shí)鐘
LPC_UART->LCR = 0x83; //8位傳輸,1個(gè)停止位,無幾偶校驗(yàn),允許訪問除數(shù)鎖存器
DL_value = SystemCoreClock/16/baudrate ; //計(jì)算該波特率要求的除數(shù)鎖存寄存器值
LPC_UART->DLM = DL_value / 256; //寫除數(shù)鎖存器高位值
LPC_UART->DLL = DL_value % 256; //寫除數(shù)鎖存器低位值
LPC_UART->LCR = 0x03; //DLAB置0
LPC_UART->FCR = 0x07; //允許FIFO,清空RxFIFO 和 TxFIFO
Clear = LPC_UART->LSR; //讀UART狀態(tài)寄存器將清空殘留狀態(tài)
}
/************************************************/
/* 函數(shù)功能:串口接收字節(jié)數(shù)據(jù) */
/************************************************/
uint8_t UART_recive(void)
{
while(!(LPC_UART->LSR & (1<<0))); //等待接收到數(shù)據(jù)
return(LPC_UART->RBR); //讀出數(shù)據(jù)
}
/************************************************/
/* 函數(shù)功能:串口發(fā)送字節(jié)數(shù)據(jù) */
/************************************************/
void UART_send_byte(uint8_t byte)
{
while ( !(LPC_UART->LSR & (1<<5)) );//等待發(fā)送完
LPC_UART->THR = byte;
}
/************************************************/
/* 函數(shù)功能:串口發(fā)送數(shù)組數(shù)據(jù) */
/************************************************/
void UART_send(uint8_t *Buffer, uint32_t Length)
{
while(Length != 0)
{
while ( !(LPC_UART->LSR & (1<<5)) );//等待發(fā)送完
LPC_UART->THR = *Buffer;
Buffer++;
Length--;
}
}
void I2C_Init(uint8_t Mode)
{
LPC_SYSCON->PRESETCTRL |= (1<<1); //使I2C上電 I2C模塊(在啟動I2C模塊之前,必須向該位寫1)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //使能I2C時(shí)鐘
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘
LPC_IOCON->PIO0_4 &= ~0x3F;
LPC_IOCON->PIO0_4 |= 0x01; //把P0.4腳配置為 I2C SCL
LPC_IOCON->PIO0_5 &= ~0x3F;
LPC_IOCON->PIO0_5 |= 0x01; //把P0.5腳配置為 I2C SDA
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘
if(Mode == 1) // 快速I2C通信 (大約400KHz傳輸速率)
{
LPC_I2C->SCLH = 60;
LPC_I2C->SCLL = 65;
}
if(Mode == 2) //快速+I2C通信 (大約1M傳輸速率)
{
LPC_I2C->SCLH = 25;
LPC_I2C->SCLL = 25;
}
else // 低速I2C通信 (大約100KHz傳輸速率)
{
LPC_I2C->SCLH = 250;
LPC_I2C->SCLL = 250;
}
LPC_I2C->CONCLR = 0xFF; // 清所有標(biāo)志(CONCLR的置1操作的)
LPC_I2C->CONSET |= I2CONSET_I2EN; // 使能I2C接口
}
/***************************************************
/* 函數(shù)功能:發(fā)送開始信號 */
/***************************************************
void I2C_Start(void)
{
LPC_I2C->CONSET |= I2CONSET_STA; // 使能發(fā)送開始信號
while(!(LPC_I2C->CONSET & I2CONSET_SI)); // 等待開始信號發(fā)送完成
LPC_I2C->CONCLR = I2CONCLR_STAC | I2CONCLR_SIC; // 清除開始START位和SI位
}
/***************************************************/
/* 函數(shù)功能:發(fā)送停止信號 */
/***************************************************/
void I2C_Stop(void)
{
LPC_I2C->CONCLR = I2CONCLR_SIC; // 清SI標(biāo)志位
LPC_I2C->CONSET |= I2CONSET_STO; // 發(fā)送停止信號
while( LPC_I2C->CONSET & I2CONSET_STO ); // 等待停止信號發(fā)送完成
}
/****************************************************/
/* 函數(shù)功能:I2C發(fā)送一字節(jié)數(shù)據(jù) */
/* 入口參數(shù):dat : 要發(fā)送的字節(jié) */
/***************************************************/
void I2C_Send_Byte(uint8_t dat)
{
uint16_t TimeOut;
LPC_I2C->DAT = dat; // 把字節(jié)寫入DAT寄存器
LPC_I2C->CONCLR = I2CONSET_SI; // 清除SI標(biāo)志(1<<3)
TimeOut=20000;//或延時(shí)10000
while((!(LPC_I2C->CONSET & I2CONSET_SI))&&(TimeOut--)); // 等待數(shù)據(jù)發(fā)送完成
}
/***************************************************/
/* 函數(shù)功能:I2C接收一字節(jié)數(shù)據(jù) */
/* 入口參數(shù):rebyte : 要接收的字節(jié) */
/***************************************************/
uint8_t I2C_Recieve_Byte(void)
{
uint8_t rebyte;
uint16_t TimeOut;
LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC; // 清AA和SI標(biāo)志
TimeOut=20000;
while((!(LPC_I2C->CONSET & I2CONSET_SI))&&(TimeOut--)); // 等待接收數(shù)據(jù)完成
rebyte = (uint8_t)LPC_I2C->DAT; // 把接收到的數(shù)據(jù)給了rebyte
return rebyte;
}
/****************************************************/
/* 函數(shù)功能:I2C發(fā)送命令數(shù)據(jù) */
/* 入口參數(shù):Ctrl : 命令+地址字節(jié) */
/* 出口參數(shù):0:成功 */
/* 1: 失敗 */
/***************************************************/
uint8_t I2C_Send_Ctrl(uint8_t CtrlAndAddr)
{
uint8_t res;
uint16_t TimeOut;
if(CtrlAndAddr & 0x01) // 如果是讀命令
res = 0x40; // 40H代表開始信號和讀命令已經(jīng)傳輸完畢,并且已經(jīng)接收到ACK
else // 如果是寫命令
res = 0x18; // 18H代表開始信號和寫命令已經(jīng)傳輸完畢,并且已經(jīng)接收到ACK
// 發(fā)送開始信號
LPC_I2C->CONCLR = 0xFF; // 清所有標(biāo)志位
LPC_I2C->CONSET |= I2CONSET_I2EN | I2CONSET_STA; // 使能發(fā)送開始信號
TimeOut=20000;
while((!(LPC_I2C->CONSET & I2CONSET_SI))&&(TimeOut--)); // 等待開始信號發(fā)送完成
// 發(fā)送命令+地址字節(jié)
LPC_I2C->DAT = CtrlAndAddr; // 把要發(fā)送的字節(jié)給了DAT寄存器
LPC_I2C->CONCLR = I2CONCLR_STAC | I2CONCLR_SIC; // 清除開始START位和SI位
TimeOut=20000;
while((!(LPC_I2C->CONSET & I2CONSET_SI))&&(TimeOut--)); // 等待數(shù)據(jù)發(fā)送完成
if(LPC_I2C->STAT != res) // 觀察STAT寄存器響應(yīng)的狀態(tài),判斷是否正確執(zhí)行讀或?qū)懨? {
I2C_Stop(); // 沒有完成任務(wù),發(fā)送停止信號,結(jié)束I2C通信
return 1; // 返回1,表明失?。? }
return 0; // 如果正確執(zhí)行返回0
}
/**********************************************/
/* 溫度傳感器LM75BD的數(shù)據(jù)讀取函數(shù) */
/**********************************************/
uint16_t Temputerature_Test(void)
{
uint16_t Temputerature_8,Temputerature_16; //溫度值,1次接收8位
float Temputerature; //存儲獲得的溫度值
//IIC啟動---默認(rèn)配置溫度模式
I2C_Start();
//發(fā)送(0x91)1001 0001:1001,硬件布線; 0001,從機(jī)地址--000 讀模式--1
I2C_Send_Byte(0x91);
Temputerature_8 = I2C_Recieve_Byte();//讀LM75BD溫度寄存器的高八位數(shù)據(jù)
Temputerature_16 = (Temputerature_8 <<8)+(I2C_Recieve_Byte());
// IIC停止
I2C_Stop();
//取溫度數(shù)字量
Temputerature_16 = Temputerature_16 >> 5;//1LSB=0.125℃---低五位為無效數(shù)據(jù)(移出)
/* Temputerature_16:溫度寄存器的數(shù)據(jù)D0--D10:其中D10為溫度的正負(fù)數(shù)據(jù)*/
//負(fù)溫度
if(Temputerature_16&0x0400)
Temputerature = -(~(Temputerature_16&0x03FF)+1)*0.125;//負(fù)溫度的數(shù)據(jù)的轉(zhuǎn)換(二進(jìn)制的補(bǔ)碼+1)
//正溫度
else
Temputerature = 0.125*(float)Temputerature_16;
//返回溫度值 1LSB=0.01℃
return ((uint16_t)(Temputerature*100));//返回的溫度數(shù)據(jù)擴(kuò)大了100倍便于讀出小數(shù)部分;
}
uint8_t rec_buf; //串口接收數(shù)據(jù)
uint16_t temp; //獲的溫度傳感器LM75BD的數(shù)據(jù)
uint8_t buf[6]={0+'0',1+'0',0+'0'}; //初始值--測試串口發(fā)送數(shù)據(jù)
/**********************************************/
/* 軟件延時(shí)函數(shù) */
/**********************************************/
void delay(void)
{
uint16_t i,j;
for(i=0;i<500;i++)
for(j=0;j<1000;j++);
}
/**********************************************/
/* 獲得溫度傳感器LM75BD的數(shù)據(jù) */
/**********************************************/
void Get_temprature(void)
{
temp=Temputerature_Test();
buf[0]=temp/10000+'0';
if((temp/10000)==0) buf[0]=' '; // 數(shù)據(jù)讀取習(xí)慣--去除前面的0
buf[1]=temp/1000%10+'0';
buf[2]=temp/100%10+'0';
buf[3]='.';
buf[4]=temp/10%10+'0'; // 小數(shù)部分
buf[5]=temp%10+'0';
}
/**********************************************/
/* 中斷服務(wù)子程序函數(shù) */
/**********************************************/
void TIMER32_0_IRQHandler(void){ //中斷服務(wù)子程序
if((LPC_TMR32B0->IR|=0x01)==1){ //判斷MR0是否中斷并清零中斷
Get_temprature(); // 獲得溫度數(shù)據(jù)
UART_send((uint8_t*)"Current Temperature is:",23); // 串口發(fā)送字符串?dāng)?shù)組
UART_send(buf,6);
UART_send_byte('C'); // 單位:攝氏度
UART_send((uint8_t*)"\r\n",2);
}
}
/**********************************************/
/* 主函數(shù) */
/**********************************************/
int main()
{
SystemInit(); // 系統(tǒng)時(shí)鐘初始化
I2C_Init(1); // IIC初始化--模式:快速+I2C通信
UART_init(9600); // 把串口波特率配置為9600
delay(); // 初始化延時(shí)----等待相關(guān)器件配置完成
//串口測試正常
UART_send((uint8_t*)"UART is ok!\r\n", 13); // 串口發(fā)送字符串?dāng)?shù)組
UART_send((uint8_t*)"UART Test Data:", 15);
UART_send(buf,3);
UART_send((uint8_t*)"\r\n",2);
Temputerature_Test(); //進(jìn)行一次讀取(過濾第一個(gè)數(shù)據(jù))--第一次讀取的數(shù)據(jù)溫度不準(zhǔn)確
TMR32B0_Init(); //中斷子程序
while(1)
{
}
}
作業(yè)7FLASH存儲器操作
(1)初始化LPC1114微控制器UART串行口,定時(shí)器、I2C總線接口、SSP串行端口為SPI幀格式;
(2)系統(tǒng)啟動后,利用通用定時(shí)器實(shí)現(xiàn)定時(shí)1s中斷,在定時(shí)器中斷服務(wù)子程序中讀取LM75BD(I2C總線)當(dāng)前溫度值,并通過SPI接口將讀到的溫度值存儲到FLASH存儲器XT25F02中,在PC上利用串口調(diào)試助手向LPC1114的UART接口發(fā)送讀取命令,從FLASH存儲器中讀出溫度數(shù)據(jù),并通過UART接口發(fā)送到PC,利用串口調(diào)試助手接收溫度數(shù)據(jù)(保留3位小數(shù))。
#include "lpc11xx.h"
#define NCS LPC_GPIO2->DATA|=(1<<0) // F_CS = 1;高
#define ECS LPC_GPIO2->DATA&=~(1<<0) // F_CS = 0;低
#define GBK_EN
//W25Q16讀寫
#define FLASH_ID 0XEF14
//指令表
#define W25Q_WriteEnable 0x06
#define W25Q_WriteDisable 0x04
#define W25Q_ReadStatusReg 0x05
#define W25Q_WriteStatusReg 0x01
#define W25Q_ReadData 0x03
#define W25Q_FastReadData 0x0B
#define W25Q_FastReadDual 0x3B
#define W25Q_PageProgram 0x02
#define W25Q_BlockErase 0xD8
#define W25Q_SectorErase 0x20
#define W25Q_ChipErase 0xC7
#define W25Q_PowerDown 0xB9
#define W25Q_ReleasePowerDown 0xAB
#define W25Q_DeviceID 0xAB
#define W25Q_ManufactDeviceID 0x90
#define W25Q_JedecDeviceID 0x9F
void W25Q16_Wait_Busy(void); //等待空閑
uint16_t wendu;
uint8_t buff[7];
uint8_t Wdata[7];
uint8_t Rdata[7];
uint32_t flashdizhi;
uint8_t output=0;
int j;
/************************ssp*************************
/* 函數(shù)功能:SPI1通信 */
/* 說明: 發(fā)送一個(gè)字節(jié),接收一個(gè)字節(jié) */
/*****************************************/
uint8_t SPI1_communication(uint8_t TxData)
{
while(((LPC_SSP1->SR)&(1<<4))==(1<<4));//忙時(shí)等待,SR狀態(tài)寄存器bit4 BSY:忙時(shí)為1
LPC_SSP1->DR = TxData; //把要發(fā)送的數(shù)寫入TxFIFO
while(((LPC_SSP1->SR)&(1<<2))!=(1<<2));//等待接收完,SR狀態(tài)寄存器bit2 RNE:接收FIFO非空為1
return(LPC_SSP1->DR); //返回收到的數(shù)據(jù)
}
/*****************************************/
/* 函數(shù)功能:SPI0通信 */
/* 說明: 發(fā)送一個(gè)字節(jié),接收一個(gè)字節(jié) */
/*****************************************/
uint8_t SPI0_communication(uint8_t TxData)
{
while(((LPC_SSP0->SR)&(1<<4))==(1<<4));//忙時(shí)等待,SR狀態(tài)寄存器bit4 BSY:忙時(shí)為1
LPC_SSP0->DR = TxData; //把要發(fā)送的數(shù)寫入TxFIFO
while(((LPC_SSP0->SR)&(1<<2))!=(1<<2));//等待接收完,SR狀態(tài)寄存器bit2 RNE:接收FIFO非空為1
return(LPC_SSP0->DR); //返回收到的數(shù)據(jù)
}
/*****************************************/
/* 函數(shù)功能:SPI1初始化 */
/* 說明: 沒有用SSEL1 */
/*****************************************/
void SPI1_Init(void)
{
uint8_t i,Clear=Clear;//Clear=Clear:用這種語句形式解決編譯產(chǎn)生的Waring:never used!
LPC_SYSCON->PRESETCTRL |= (0x1<<2); //禁止LPC_SSP1復(fù)位
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<18);//允許LPC_SSP1時(shí)鐘 bit18
LPC_SYSCON->SSP1CLKDIV = 0x06; //6分頻:48/6=8Mhz
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘(bit16)
LPC_IOCON->PIO2_1 &= ~0x07;
LPC_IOCON->PIO2_1 |= 0x02; //把PIO2_1選擇為LPC_SSP CLK
LPC_IOCON->PIO2_2 &= ~0x07;
LPC_IOCON->PIO2_2 |= 0x02; //把PIO2_2選擇為LPC_SSP MISO
LPC_IOCON->PIO2_3 &= ~0x07;
LPC_IOCON->PIO2_3 |= 0x02; //把PIO2_3選擇為LPC_SSP MOSI
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘(bit16)
// 8位數(shù)據(jù)傳輸,SPI模式, CPOL = 1, CPHA = 1,空閑時(shí)CLK為1,SCR = 0
LPC_SSP1->CR0 = 0x01C7; //1 1100 0111
// 預(yù)分頻值(注意:這里必須為偶數(shù) 2~254)
LPC_SSP1->CPSR = 0x04;
LPC_SSP1->CR1 &= ~(1<<0);//LBM=0:正常模式
LPC_SSP1->CR1 &= ~(1<<2);//MS=0:主機(jī)模式
LPC_SSP1->CR1 |= (1<<1);//SSE=1:使能SPI1
//清空RxFIFO,LPC1114收發(fā)均有8幀F(xiàn)IFO,每幀可放置4~16位數(shù)據(jù)
for ( i = 0; i < 8; i++ )
{
Clear = LPC_SSP1->DR;//讀數(shù)據(jù)寄存器DR將清空RxFIFO
}
}
/*****************************************/
/* 函數(shù)功能:SPI0初始化 */
/* 說明: 沒有用SSEL0 */
/*****************************************/
void SPI0_Init(void)
{
uint8_t i,Clear=Clear;//Clear=Clear:用這種語句形式解決編譯產(chǎn)生的Waring:never used!
LPC_SYSCON->PRESETCTRL |= (0x1<<0); //禁止LPC_SSP0復(fù)位
LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<11);//允許LPC_SSP0時(shí)鐘 bit11
LPC_SYSCON->SSP0CLKDIV = 0x01; //分頻系數(shù)為1,使SPI0速率最大:48Mhz
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘(bit16)
LPC_IOCON->SCK_LOC = 0x02; //把SCK0復(fù)用到PIO0_6引腳
LPC_IOCON->PIO0_6 &= ~0x07;
LPC_IOCON->PIO0_6 |= 0x02; //把PIO0_6設(shè)置為SSP CLK
LPC_IOCON->PIO0_8 &= ~0x07;
LPC_IOCON->PIO0_8 |= 0x01; //把PIO0_8設(shè)置為SSP MISO
LPC_IOCON->PIO0_9 &= ~0x07;
LPC_IOCON->PIO0_9 |= 0x01; //把PIO0_9設(shè)置為SSP MOSI
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘(bit16)
// 8位數(shù)據(jù)傳輸,SPI模式, CPOL = 0, CPHA = 0,空閑時(shí)CLK為0,第一個(gè)上升沿采集數(shù)據(jù),SCR = 0
LPC_SSP0->CR0 = 0x0107;
// 預(yù)分頻值(注意:必須為偶數(shù) 2~254)
LPC_SSP0->CPSR = 0x02;
LPC_SSP0->CR1 &= ~(1<<0);//LBM=0:正常模式
LPC_SSP0->CR1 &= ~(1<<2);//MS=0:主機(jī)模式
LPC_SSP0->CR1 |= (1<<1);//SSE=1:使能SPI0
//清空RxFIFO,LPC1114收發(fā)均有8幀F(xiàn)IFO,每幀可放置4~16位數(shù)據(jù)
for ( i = 0; i < 8; i++ )
{
Clear = LPC_SSP0->DR;//讀數(shù)據(jù)寄存器DR將清空RxFIFO
}
}
/************************************************/
/* 函數(shù)功能:初始化UART口 */
/************************************************/
void UART_Init(uint32_t baudrate)
{
uint32_t DL_value,Clear=Clear; // (用這種方式定義變量解決編譯器的Warning)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘
LPC_IOCON->PIO1_6 &= ~0x07;
LPC_IOCON->PIO1_6 |= 0x01; //把P1.6腳設(shè)置為RXD
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01; //把P1.7腳設(shè)置為TXD
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘
LPC_SYSCON->UARTCLKDIV = 0x1; //時(shí)鐘分頻值為1
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);//允許UART時(shí)鐘
LPC_UART->LCR = 0x83; //8位傳輸,1個(gè)停止位,無幾偶校驗(yàn),允許訪問除數(shù)鎖存器
DL_value = SystemCoreClock/16/baudrate ; //計(jì)算該波特率要求的除數(shù)鎖存寄存器值
LPC_UART->DLM = DL_value / 256; //寫除數(shù)鎖存器高位值
LPC_UART->DLL = DL_value % 256; //寫除數(shù)鎖存器低位值
LPC_UART->LCR = 0x03; //DLAB置0
LPC_UART->FCR = 0x07; //允許FIFO,清空RxFIFO 和 TxFIFO
Clear = LPC_UART->LSR; //讀UART狀態(tài)寄存器將清空殘留狀態(tài)
}
/************************************************/
/* 函數(shù)功能:串口接收字節(jié)數(shù)據(jù) */
/************************************************/
uint8_t UART_receive(void)
{
while(!(LPC_UART->LSR & (1<<0)));//等待接收到數(shù)據(jù)
return(LPC_UART->RBR); //讀出數(shù)據(jù)
}
/************************************************/
/* 函數(shù)功能:串口發(fā)送字節(jié)數(shù)據(jù) */
/************************************************/
void UART_send_byte(uint8_t byte)
{
LPC_UART->THR = byte;
while ((LPC_UART->LSR & (1<<5))!=(1<<5));//等待發(fā)送完
}
/************************************************/
/* 函數(shù)功能:串口發(fā)送數(shù)組數(shù)據(jù) */
/************************************************/
void UART_send(uint8_t *Buffer, uint32_t Length)
{
while(Length != 0)
{
while ( !(LPC_UART->LSR & (1<<5)) );//等待發(fā)送完
LPC_UART->THR = *Buffer;
Buffer++;
Length--;
}
}
/*********************************************W25Q16***********************************************/
void W25Q16_Init(void)
{
//初始化W25Q16的控制IO口
LPC_GPIO2->DIR |= (1<<0); // P2.0為w25q16的選擇引腳所連接的IO
LPC_GPIO2->DATA |= (1<<0); //
SPI1_Init(); //初始化SPI1
}
//讀W25Q16狀態(tài)寄存器 */
uint8_t W25Q16_ReadSR(void)
{
uint8_t byte=0;
ECS; //選擇
SPI1_communication(W25Q_ReadStatusReg); //發(fā)送讀取狀態(tài)寄存器命令
byte=SPI1_communication(0Xff); //讀取一個(gè)字節(jié)
NCS; //取消片選
return byte; //返回8位W25Q16的狀態(tài)值
}//寫入使能
void W25Q16_Write_Enable(void)
{
ECS; //使能器件
SPI1_communication(W25Q_WriteEnable); //發(fā)送寫使能
NCS; //取消片選
}
/***************************************************函數(shù)功能:讀取W25Q16數(shù)據(jù) */
Buffer:讀出數(shù)據(jù)后放到此數(shù)組
Addr:開始讀取的地址(24bit)
ByteNum:要讀取的字節(jié)數(shù)(最大65535)
****************************************************
void W25Q16_Read(uint8_t* Buffer,uint32_t Addr,uint16_t ByteNum)
{
uint16_t i;
ECS; //使能器件
SPI1_communication(W25Q_ReadData); //發(fā)送讀取命令
SPI1_communication((uint8_t)((Addr)>>16)); //發(fā)送24bit地址
SPI1_communication((uint8_t)((Addr)>>8));
SPI1_communication((uint8_t)Addr);
for(i=0;i<ByteNum;i++)
{
Buffer[i]=SPI1_communication(0XFF); //循環(huán)讀數(shù)
}
NCS; //取消片選
}
/***************************************************函數(shù)功能:給W25Q16寫入一頁數(shù)據(jù) */
Buffer:此數(shù)組存放將要寫入W25Q16的數(shù)據(jù)
Addr:開始寫入的地址(24bit)
ByteNum:要寫入的字節(jié)數(shù)(最大256)
最多寫入256個(gè)字節(jié),而且不能超過該頁的剩余字節(jié)數(shù),否則將會覆蓋該頁前面的數(shù)據(jù)。 */
/***************************************************/
void W25Q16_Write_Page(uint8_t* Buffer,uint32_t Addr,uint16_t ByteNum)
{
uint16_t i;
W25Q16_Write_Enable(); // 發(fā)送寫使能命令
ECS; //使能SPI通信
SPI1_communication(W25Q_PageProgram); //發(fā)送寫頁命令
SPI1_communication((uint8_t)((Addr)>>16)); //發(fā)送24bit地址
SPI1_communication((uint8_t)((Addr)>>8));
SPI1_communication((uint8_t)Addr);
for(i=0;i<ByteNum;i++)SPI1_communication(Buffer[i]);//循環(huán)寫數(shù)
NCS; // 禁能SPI通信
W25Q16_Wait_Busy(); //等待寫入結(jié)束
}
函數(shù)功能;擦除整片W25Q16
/*****************************************************/
void W25Q16_Erase_Chip(void)
{
W25Q16_Write_Enable(); //SET WEL
W25Q16_Wait_Busy();
ECS; //使能器件
SPI1_communication(W25Q_ChipErase); //發(fā)送片擦除命令
NCS; //取消片選
W25Q16_Wait_Busy(); //等待芯片擦除結(jié)束
}
void W25Q16_Wait_Busy(void)
{
while ((W25Q16_ReadSR()&0x01)==0x01); // 等待BUSY位清空
}
/********I2C*****************************************/
void I2C_Init(uint8_t Mode)
{
LPC_SYSCON->PRESETCTRL |= (1<<1); //復(fù)位I2C外設(shè) De-asserted I2C 模塊(在啟動 I2C 模塊之前,必須向該位寫 1)
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //使能I2C時(shí)鐘
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); //使能I/O 配置模塊的時(shí)鐘
LPC_IOCON->PIO0_4 &= ~0x3F; //先清零
LPC_IOCON->PIO0_4 |= 0x01; //選擇 I2C 功能 SCL ( 開漏引腳 )
LPC_IOCON->PIO0_5 &= ~0x3F;
LPC_IOCON->PIO0_5 |= 0x01; //選擇 I2C 功能 SDA ( 開漏引腳 )
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 低功耗考慮
if(Mode == 1) // 快速模式400KHZ
{
LPC_I2C->SCLH = 60;
LPC_I2C->SCLL = 65;
}
if(Mode == 2) //I2C快速模式PLUS1MHZ
{
LPC_I2C->SCLH = 25;
LPC_I2C->SCLL = 25;
}
else // 標(biāo)準(zhǔn)模式100KHZ
{
LPC_I2C->SCLH = 250;
LPC_I2C->SCLL = 250;
}
LPC_I2C->CONCLR = 0xFF; //清除所有I2C0CONSET寄存器的位
LPC_I2C->CONSET |= (1<<6); // I2EN=1 使能I2C接口
}
//I2C啟動子程序(主控發(fā)送開始信號)
void I2C_Start(void)
{
LPC_I2C->CONSET |= (1<<5); // STA=1 I2C進(jìn)入主模式并發(fā)送一個(gè)起始條件
while(!(LPC_I2C->CONSET & (1<<3))); // 當(dāng)I2C狀態(tài)改變時(shí),I2C中斷標(biāo)志位3即SI置位
LPC_I2C->CONCLR = (1<<5) | (1<<3); // 清零I2C中斷位和START標(biāo)志位
}
//I2C停止子程序
void I2C_Stop(void)
{
LPC_I2C->CONCLR = (1<<3); //清除 SI標(biāo)志位
LPC_I2C->CONSET |= (1<<4); //發(fā)出停止條件,設(shè)置停止標(biāo)志位
while( LPC_I2C->CONSET & (1<<4) ); //等待停止標(biāo)志位被自動清除
}
//發(fā)送一個(gè)字節(jié)數(shù)據(jù)
void I2C_Send_Byte(uint8_t dat)
{
uint16_t TimeOut;
LPC_I2C->DAT=dat; //包含要發(fā)送的數(shù)據(jù)
LPC_I2C->CONCLR = (1<<3); // 清除中斷
TimeOut=20000; //???10000
while((!(LPC_I2C->CONSET & (1<<3)))&&(TimeOut--));
}
//接收一個(gè)字節(jié)數(shù)據(jù)
uint8_t I2C_Recieve_Byte(void)
{
uint8_t Rdata;
uint16_t TimeOut;
LPC_I2C->CONSET = (1<<2); //AA位置1,在出現(xiàn)特定情況時(shí)返回應(yīng)答信號
LPC_I2C->CONCLR = (1<<3); //中斷位清零
TimeOut=20000;
while((!(LPC_I2C->CONSET & (1<<3)))&&(TimeOut--));
Rdata = (uint8_t)LPC_I2C->DAT; //收到的數(shù)據(jù)
return Rdata;
}
/*****************************************TEM******/
void delay(void)
{
uint16_t i,j;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++);
}
uint16_t cewen(void)
{
uint8_t front8bit,after8bit;
uint16_t wendu16bit;
float T;
I2C_Start();
I2C_Send_Byte(0x91);
front8bit = I2C_Recieve_Byte();
after8bit = I2C_Recieve_Byte();
wendu16bit = (front8bit <<8)+(after8bit);
I2C_Stop();
wendu16bit = wendu16bit >> 5;
if(wendu16bit&0x0400) //10000000000溫度采用二進(jìn)制補(bǔ)碼表示
T = -(~(wendu16bit&0x03FF)+1)*0.125;
else
T = 0.125*(float)wendu16bit;
return ((uint16_t)(T*1000));
}
void Get_wendu(void)
{
wendu=cewen();
buff[0]=wendu/100000+'0';
if((wendu/100000)==0) buff[0]=' ';
buff[1]=wendu/10000%10+'0';
buff[2]=wendu/1000%10+'0';
buff[3]='.';
buff[4]=wendu/100%10+'0'; // 小數(shù)點(diǎn)部分
buff[5]=wendu/10%10+'0';
buff[6]=wendu%10+'0';
}
void TMR32B0_Init(void){ /*32位定時(shí)器0初始化*/
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<9); //使能
LPC_TMR32B0->IR=0x1F; //中斷清0
LPC_TMR32B0->PR=9; //分頻9 9+1=10,1s
LPC_TMR32B0->MCR=3; //匹配后復(fù)位TC并中斷
LPC_TMR32B0->MR0=SystemCoreClock/10; //中斷時(shí)間0.1s
LPC_TMR32B0->TCR=0x01; //使能定時(shí)器
NVIC_EnableIRQ(TIMER_32_0_IRQn); //設(shè)置中斷并使能
}
/* 中斷服務(wù)子程序函數(shù) */
/**********************************************/
void TIMER32_0_IRQHandler(void){ //中斷服務(wù)子程序
if(!output&&LPC_UART->RBR=='s'){ //判斷輸入s開始發(fā)送
output=1;
}
if((LPC_TMR32B0->IR|=0x01)==1){ //判斷MR0是否中斷并清零中斷
Get_wendu();
if(output){
W25Q16_Write_Page(buff,flashdizhi,7) ; //溫度一位一位寫入flash
W25Q16_Read(Rdata, flashdizhi, 7); //讀出存到Rdata
delay();
UART_send(Rdata, 7); //發(fā)送數(shù)據(jù)
UART_send("\r\n",2);
flashdizhi+=6;
}
}
}
int main()
{
UART_Init(9600);
W25Q16_Init();
SystemInit();
I2C_Init(1);
flashdizhi = 0x000; // 從W25Q16第0個(gè)扇區(qū)第一個(gè)字節(jié)開始寫入數(shù)據(jù)
W25Q16_Erase_Chip() ; //擦除
TMR32B0_Init(); //定時(shí)器初始化
while(1)
{
}
}
作業(yè)8 ADC模數(shù)轉(zhuǎn)換
(1)初始化LPC1114微控制器UART串行口,AD轉(zhuǎn)換器分別初始化為軟件控制模式(CR中的BURST位為0,立即啟動、硬件觸發(fā)[1])和硬件掃描模式(CR中的BURST位為1),開啟AD中斷,設(shè)置AD0為模擬輸入引腳;
(2)啟動AD轉(zhuǎn)換,在AD中斷服務(wù)子程序中讀取AD轉(zhuǎn)換的值(AD0通道),并通過UART接口發(fā)送到PC,利用串口調(diào)試助手接收數(shù)據(jù)。
#include "LPC11xx.h" /* LPC11xx definitions */
/*-----------------------------------------------------------------------------
The Subfunction
*----------------------------------------------------------------------------*/
uint32_t regVal;
uint32_t ADC0_Value;
void UART_init(void) /* Init the UART function */
{
LPC_SYSCON->SYSAHBCLKCTRL|=((1UL<<6)|(1UL<<16)); //使能IOCON時(shí)鐘
LPC_IOCON->PIO1_6=(1UL<<0); /* Definit P1.6 as RxD */
LPC_IOCON->PIO1_7=(1UL<<0);/* Definit P1.7 as TxD */
LPC_SYSCON->SYSAHBCLKCTRL|=(1UL<<12);//′打開串口時(shí)鐘,配置完串口也不要關(guān)閉,因?yàn)榇诠ぷ餍枰獣r(shí)鐘
LPC_SYSCON->UARTCLKDIV=(4UL<<0); /* UART clock = CCLK/4 */
LPC_UART->LCR=0x83; // 配置U0LCR寄存器,8位傳輸,1個(gè)停止位,無奇偶校驗(yàn),允許訪問除數(shù)鎖存器
LPC_UART->DLL=4; /* 115200 Baud Rate @ 12.0MHz PCLK */
LPC_UART->FDR=0x85; /* FR=1.627,DIVADVAL=5,MULVAL=8 */
LPC_UART->DLM=0; /* High divisor latch=0 */
LPC_UART->LCR=0x03; //DLAB置0
LPC_UART->IER=0x01; //啟用 UART 中斷功能
LPC_UART->FCR=0x81; //將接收緩沖區(qū)長度設(shè)置為 8B
NVIC_EnableIRQ(UART_IRQn); //定義中斷功能
}
void UART_SendBytes(uint32_t data16send) //通過搜索 U0LSR 發(fā)送數(shù)據(jù)
{
LPC_UART->THR=data16send; //將發(fā)送數(shù)據(jù)放入 THR
while((LPC_UART->LSR&0x40)==0); }
void TIM16B0_MAT_Init(uint16_t a){
LPC_SYSCON->SYSAHBCLKCTRL|=(1<<7); // 使能定時(shí)器0時(shí)鐘
LPC_IOCON->PIO0_8=0x02; /配置PIO0_8為定時(shí)器16B0的MAT0功能 LPC_TMR16B0->TCR=0x02; 設(shè)置定時(shí)器16B0為復(fù)位狀態(tài) LPC_TMR16B0->PR=SystemCoreClock/1000-1; // 設(shè)置定時(shí)器分頻,以1毫秒為基準(zhǔn) LPC_TMR16B0->MR0=a; // 設(shè)置定時(shí)器MAT0的值 LPC_TMR16B0->IR=0x01; // 清除中斷標(biāo)志 LPC_TMR16B0->MCR=0x02; // 當(dāng)計(jì)數(shù)器與MAT0匹配時(shí),產(chǎn)生中斷
LPC_TMR16B0->EMR=0x31; // 定時(shí)器16B0的MAT0輸出翻轉(zhuǎn)模式
LPC_TMR16B0->TCR=0x01; // 啟動計(jì)時(shí)器
}
void ADC_Init(void)
{
// 使能 ADC 和 IOCON 外設(shè)的時(shí)鐘
LPC_SYSCON->SYSAHBCLKCTRL |= ((1UL<<6) | (1UL<<16));
// 上電 ADC 模塊
LPC_SYSCON->PDRUNCFG &= ~(1UL<<4);
// 使能 ADC 外設(shè)的時(shí)鐘
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL<<13);
// 配置 P0.11 引腳為 ADC 輸入
LPC_IOCON->R_PIO0_11 |= 0x82; // 選擇 ADC 功能并禁用上拉電阻
LPC_IOCON->R_PIO0_11 |= 0x02; // 將引腳設(shè)置為 AD0
LPC_IOCON->R_PIO0_11 &= ~(1UL<<7); // 配置引腳為模擬輸入模式
// 配置 ADC 控制寄存器
LPC_ADC->CR = (1UL<<0) | (23UL<<8) | (1UL<<25) | (1UL<<26) | (1UL<<27
// 使能 ADC 轉(zhuǎn)換完成中斷
LPC_ADC->INTEN = (1UL<<0);
// 使能 ADC 轉(zhuǎn)換完成中斷的 NVIC 中斷向量
NVIC_EnableIRQ(ADC_IRQn);
// 初始化定時(shí)器 16B0,用于控制 ADC 轉(zhuǎn)換頻率
TIM16B0_MAT_Init(500);
}
void ADC_IRQHandler(void)
{
// 讀取 ADC 狀態(tài)寄存器
regVal = LPC_ADC->STAT;
// 讀取 ADC 數(shù)據(jù)寄存器,獲取 ADC 轉(zhuǎn)換結(jié)果
regVal = LPC_ADC->DR[0];
// 提取 ADC 轉(zhuǎn)換結(jié)果的有效數(shù)據(jù),并保存到 ADC0_Value 變量中
ADC0_Value = (regVal >> 6) & 0x3ff;
// 將 ADC 轉(zhuǎn)換結(jié)果轉(zhuǎn)換為電壓值(單位:伏特),并發(fā)送到串口
regVal = (ADC0_Value * 3.3) / 1024;
UART_SendBytes(regVal >> 8); // 發(fā)送高字節(jié)
UART_SendBytes(regVal); // 發(fā)送低字節(jié)
}
void delay(void)//一個(gè)自動生成的延時(shí)函數(shù)
{
uint16_t i,j;
for(j=0;j<5000;j++)
for(i=0;i<500;i++);
}
int main (void) { /* Main Program */
UART_init(); /* Init the UART function */
ADC_Init();
delay();
while(1){
}
}
作業(yè)9? 電源管理與功率控制
(1)立即睡眠:初始化LPC1114,SysTick定時(shí)100ms,在異常服務(wù)子程序中設(shè)置一個(gè)計(jì)數(shù)器,每計(jì)10個(gè)數(shù)就設(shè)置PIO1_9引腳狀態(tài)反轉(zhuǎn),在主程序中調(diào)用__WFI( )內(nèi)部函數(shù),進(jìn)入睡眠模式,觀察系統(tǒng)節(jié)拍定時(shí)器中斷是否可以喚醒睡眠模式?并就現(xiàn)象作解釋說明。
(2)退出時(shí)睡眠:初始化LPC1114,SysTick定時(shí)100ms,在異常服務(wù)子程序中設(shè)置一個(gè)計(jì)數(shù)器,每計(jì)10個(gè)數(shù)就設(shè)置PIO1_9引腳狀態(tài)反轉(zhuǎn),設(shè)置系統(tǒng)控制寄存器SCR的SLEEPONEXIT位為1(退出時(shí)睡眠),觀察系統(tǒng)運(yùn)行狀態(tài),并作解釋說明。
(3)深度睡眠:設(shè)置系統(tǒng)控制寄存器SCR的SLEEPDEEP位為1,重復(fù)(2)的操作,觀察系統(tǒng)運(yùn)行狀態(tài),并作解釋說明。
(4)深度掉電:用文字說明如何進(jìn)入深度掉電模式,如何從深度掉電模式喚醒。
1.立即睡眠
程序:
#include <LPC11xx.h>
void Led_init(){
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // 使能時(shí)鐘
LPC_GPIO1->DIR |= (1<<9);//給高電平
}
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL <<9); /* 翻轉(zhuǎn)LED */
}
void SysTick_Handler(void){
static unsigned long ticks=0;//進(jìn)入中斷的次數(shù)
if(ticks==10){//計(jì)時(shí)10個(gè)數(shù)
LED_Toggle();//將接口取反
ticks=0;
}
ticks++;
}
int main(){
/
SystemInit();// 主時(shí)鐘設(shè)置成48Mhz
Led_init();
SysTick_Config(SystemCoreClock/10); //計(jì)時(shí)器計(jì)時(shí)100ms
__WFI();
while(1){
}
}
現(xiàn)象:LED正常閃爍
利用定時(shí)器中斷可以喚醒睡眠模式,當(dāng)SLEEPONEXIT為0時(shí),程序調(diào)用WFI命令,同時(shí)系統(tǒng)會立馬進(jìn)入睡眠模式。
在睡眠模式中,因?yàn)閟ystick為外設(shè),有自己的時(shí)鐘所以仍然可以運(yùn)行,在這里如果有中斷出現(xiàn),則處理中斷函數(shù)。在中斷函數(shù)結(jié)束后,程序這個(gè)時(shí)候?qū)⑦M(jìn)入線程模式中,開始執(zhí)行WFI后面的代碼。
系統(tǒng)節(jié)拍定時(shí)器能喚醒睡眠模式
2.退出時(shí)睡眠
#include <LPC11xx.h>
void Led_init(){
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // 使能時(shí)鐘
LPC_GPIO1->DIR |= (1<<9);//給高電平
}
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL <<9); /* Toggle the BLINKY LED */
}
void SysTick_Handler(void){
static unsigned long ticks=0;//進(jìn)入中斷的次數(shù)
if(ticks==10){//計(jì)時(shí)10個(gè)數(shù)
LED_Toggle();//將接口取反
ticks=0;
}
ticks++;
}
int main(){
SystemInit();// 主時(shí)鐘設(shè)置成48Mhz
Led_init();
SysTick_Config(SystemCoreClock/10); //計(jì)時(shí)器計(jì)時(shí)100ms
SCB->SCR |=(1<<1); //退出時(shí)睡眠
//SCB->SCR |=SCB_SCR_SLEEPONEXIT_Msk;
__WFI();
while(1){
}
}
現(xiàn)象:小燈正常閃爍
進(jìn)入睡眠,外設(shè)仍然繼續(xù)運(yùn)行,利用系統(tǒng)節(jié)拍定時(shí)器中斷喚醒睡眠模式,當(dāng)SLEEPONEXIT為1時(shí),程序調(diào)用WFI命令,系統(tǒng)會進(jìn)入睡眠模式。
在睡眠模式中,如果有中斷出現(xiàn),則進(jìn)入中斷處理函數(shù)。 在中斷函數(shù)結(jié)束后,由于SLEEPONEXIT=1 ,返回線程模式后進(jìn)入睡眠模式程序這個(gè)時(shí)候?qū)⒃俅芜M(jìn)入睡眠模式中。
3.深度睡眠
#include <LPC11xx.h>
void Led_init(){
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // 使能時(shí)鐘
LPC_GPIO1->DIR |= (1<<9);//給高電平
}
void LED_Toggle(void) {
LPC_GPIO1->DATA ^= (1UL <<9); /* Toggle the BLINKY LED */
}
void SysTick_Handler(void){
static unsigned long ticks=0;//進(jìn)入中斷的次數(shù)
if(ticks==10){//計(jì)時(shí)10個(gè)數(shù)
LED_Toggle();//將接口取反
ticks=0;
}
ticks++;
}
int main(){
SystemInit();// 主時(shí)鐘設(shè)置成48Mhz
Led_init();
SysTick_Config(SystemCoreClock/100); //計(jì)時(shí)器計(jì)時(shí)100ms
SCB->SCR |=(1<<2); //設(shè)置深度睡眠
SCB->SCR |=(1<<1); //退出時(shí) 深度睡眠
//SCB->SCR |=SCB_SCR_SLEEPONEXIT_Msk;
__WFI();
while(1){
}
}
現(xiàn)象:LED燈不亮
系統(tǒng) SLEEPDEEP=1 系統(tǒng)在調(diào)用WFI后將進(jìn)入深度睡眠模式。進(jìn)入深度睡眠模式后,中斷程序無法喚醒CPU,故LED不亮。
作業(yè)10:RTC時(shí)間設(shè)置與讀取
在Keil MDK 4.74上按照CMSIS標(biāo)準(zhǔn)編寫一段程序:
(1)初始化LPC1114微控制器UART串行口,I2C總線接口,并且初始化DS1307;
(2)讀出DS1307的實(shí)時(shí)日期和時(shí)間,通過串行口發(fā)送到PC,在PC上利用串口調(diào)試助手接收數(shù)據(jù),并通過串口調(diào)試助手發(fā)送日期和時(shí)間的設(shè)置值,觀察RTC是否能夠正常運(yùn)行。
//ds1307.c
#include <LPC11xx.h>
void I2c_Start();
void I2C_Stop();
void I2C_Send_Byte();
uint8_t I2C_Recieve_Byte();
void Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData);
void DS1307_Write(uint8_t *data);
/*函數(shù)功能:DS1307 初始化,默認(rèn)初始化為全 0*/
void DS1307Init(){
uint8_t time[7]={0x30,0x27,0x21,0x02,0x07,0x02,0x23};//設(shè)置時(shí)間 2023 年 2 月 7 日星期二 21
時(shí) 27 分 30 秒
DS1307_Write(time);
}
void DS1307_Read(uint8_t *data){
Ds1307_WriteByte(0x3f,0x01);//定位 ds1307 內(nèi)部指針到 0x3f(RAM 尾部)處
I2c_Start();//start
I2C_Send_Byte(0xd1);//讀
LPC_I2C->CONSET =(1<<2);//AA=1
data[0]=I2C_Recieve_Byte();
data[1]=I2C_Recieve_Byte();
data[2]=I2C_Recieve_Byte();
data[3]=I2C_Recieve_Byte();
data[4]=I2C_Recieve_Byte();
data[5]=I2C_Recieve_Byte();
LPC_I2C->CONCLR =(1<<2);//AA=0
data[6]=I2C_Recieve_Byte();
I2C_Stop();//STOP
}
/* 函數(shù)功能:DS1307 寫*/
void DS1307_Write(uint8_t *data){
I2c_Start();//start
I2C_Send_Byte(0xd0);//讀
LPC_I2C->CONSET =(1<<2);//AA=1
I2C_Send_Byte(0x00);//從 0x00 開始寫入
I2C_Send_Byte(data[0]);
I2C_Send_Byte(data[1]);
I2C_Send_Byte(data[2]);
I2C_Send_Byte(data[3]);
I2C_Send_Byte(data[4]);
I2C_Send_Byte(data[5]);
LPC_I2C->CONCLR =(1<<2);//AA=0
I2C_Send_Byte(data[6]);
I2C_Stop();//STOP
}
/*函數(shù)功能:DS1307 寫一個(gè)字節(jié)*/
void Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData)
{
//I2C_Start();
I2c_Start();//start
I2C_Send_Byte(0xd0); // Device Addr + Write (operation)
I2C_Send_Byte(WriteAddr);
LPC_I2C->CONCLR =(1<<2);//AA=0 接受完下一個(gè)字節(jié)后返回非應(yīng)答信號
I2C_Send_Byte(WriteData);
I2C_Stop();
}
/* 函數(shù)功能:DS1307 讀一個(gè)字節(jié)*/
uint8_t Ds1307_ReadByte()
{
uint8_t RevData;
I2c_Start();//start
I2C_Send_Byte(0xD1); // Device Addr + Write (operation)
LPC_I2C->CONCLR =(1<<2);//AA=0
RevData = I2C_Recieve_Byte();
I2C_Stop();
return RevData;
}
//I2C.c
#include <LPC11xx.h>
/*函數(shù)功能:I2C 初始化*/
void I2CInit(){
LPC_SYSCON->PRESETCTRL |= (1<<1); //復(fù)位取消
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<5);//使能 I2C
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<16);//使能 IO 配置塊
//選擇快速模式
LPC_IOCON->PIO0_4 &=~(0X3F); //選擇快速模式
LPC_IOCON->PIO0_4 |=0X01;//選擇 SCL
LPC_IOCON->PIO0_5 &=~(0X3F); //選擇快速模式
LPC_IOCON->PIO0_5 |=0X01;//選擇 SDA
//設(shè)置 SCL 頻率為 400kHZ
LPC_I2C->SCLH=40;
LPC_I2C->SCLL=80;
//使能 I2C 同時(shí)將其他控制位清 0
LPC_I2C->CONCLR=0XFF;
LPC_I2C->CONSET |=(1<<6);
}
/*函數(shù)功能:發(fā)送開始信號*/
void I2c_Start(){
LPC_I2C->CONSET =(1<<5);// 發(fā)送開始信號
while(!(LPC_I2C->CONSET&(1<<3))){//等待開始信號發(fā)送完成 SI 置位
}
LPC_I2C->CONCLR =(1<<5|1<<3); //清零 START 和 SI
}
/*函數(shù)功能:發(fā)送停止信號*/
void I2C_Stop(){
LPC_I2C->CONCLR =(1<<3);
LPC_I2C->CONSET =(1<<4);// 發(fā)送停止信號
while((LPC_I2C->CONSET&(1<<4))){//等待停止信號發(fā)送完成 SI 置位
}
}
/*函數(shù)功能:發(fā)送一個(gè)字節(jié)*/
void I2C_Send_Byte(uint8_t data){
LPC_I2C->DAT=data;
LPC_I2C->CONCLR =(1<<3); //開始發(fā)送數(shù)據(jù) 清 SI
while(!(LPC_I2C->CONSET&(1<<3))){//等待數(shù)據(jù)發(fā)送完成 SI 置位
}
}
/*函數(shù)功能:接受一個(gè)字節(jié)*/
uint8_t I2C_Recieve_Byte(){
LPC_I2C->CONCLR =(1<<3);//開始接受數(shù)據(jù) 清 SI
while(!(LPC_I2C->CONSET&(1<<3))){//等待接受數(shù)據(jù)完成 SI 置位
}
return (uint8_t)LPC_I2C->DAT;
}
//Tmr16b0.c
#include <LPC11xx.h>
void UART_Send(uint8_t str[],int lenght);
void UART_Send_Bit();
void Delay_1s();
void DS1307_Read(uint8_t *data);
void Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData);
uint8_t Ds1307_ReadByte();
uint8_t buf[100]; //存放溫度
void TMR16B0_Init(){//定時(shí)器初始化 定時(shí) 1s
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<7);//使能 16B0
LPC_TMR16B0->MCR =3; //匹配 MR0 時(shí)復(fù)位 TC 且中斷
LPC_TMR16B0->PR=799; //預(yù)分頻值 799
//LPC_TMR16B0->PR=1599; //預(yù)分頻值 1599 定時(shí) 2 秒
LPC_TMR16B0->MR0=SystemCoreClock/800; // 設(shè)置周期為 1 秒
LPC_TMR16B0->TCR=0X01; //啟動定時(shí)
NVIC_EnableIRQ(TIMER_16_0_IRQn); //啟動中斷
}
void TIMER16_0_IRQHandler(){//中斷
uint8_t data[7];
DS1307_Read(data);
UART_Send_Bit(0xff); //方便區(qū)分
UART_Send(data,7);
UART_Send_Bit(0xff);
LPC_TMR16B0->IR |=0X01; //清中斷
}
//UART.c
#include <LPC11xx.h>
uint32_t Rcv_Buf[100]; //存放數(shù)據(jù)
int buf_i=0;//數(shù)據(jù)長度
void DS1307_Write(uint8_t *data);
void Delay_1s(void);
void UARTInit(){
//配置引腳
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<16);//使能 IO
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<6) ;//使能 GPIO
LPC_IOCON->PIO1_6 |= 0x01; //設(shè)置成 RXD 引腳
LPC_IOCON->PIO1_7 |= 0x01; //設(shè)置成 TXD 引腳
LPC_UART->LCR=3; //數(shù)據(jù) 8 停止 1 無校驗(yàn)
//設(shè)置波特率 115384 近似 115200
LPC_SYSCON->SYSAHBCLKCTRL |=(1<<12);//使能 UART
LPC_SYSCON->UARTCLKDIV=4; //設(shè)置分頻值 4 獲得 UART 時(shí)鐘為 12Mhz
LPC_UART->LCR=0X83; //DLAB=1
LPC_UART->DLL=4;
LPC_UART->DLM=0;
LPC_UART->LCR=0x03; //DLAB=0
LPC_UART->FDR=0X85; //MIV=8 DIV=5
LPC_UART->FCR =0X81; //使能 FIFO 深度設(shè)置為 8
LPC_UART->IER |=1<<0; //使能接受中斷
NVIC_EnableIRQ(UART_IRQn); //啟動中斷
}
/*發(fā)送字符串*/
void UART_Send(uint8_t str[],int lenght){
int i;
for(i=0;i<lenght;i++){
LPC_UART->THR= str[i];
while((LPC_UART->LSR&0X40)==0);//等待數(shù)據(jù)發(fā)送完成
}
}
/*發(fā)送 一個(gè)字節(jié)*/
void UART_Send_Bit(uint8_t data){
LPC_UART->THR= data;
while((LPC_UART->LSR&0X40)==0);//等待數(shù)據(jù)發(fā)送完成
}
void UART_IRQHandler(){
int i;
uint8_t data[16]={0};
uint8_t adc;
for(i=0;i<16;i++){
data[i]=0x11;
}
switch(LPC_UART->IIR&0X0F){
case 0x04: //RDA
for(i=0;i<8;i++){
Rcv_Buf[buf_i++]=LPC_UART->RBR; //接受數(shù)據(jù)
}
break;
case 0x0c: //CTI
//每次都只發(fā)送 7 組數(shù)據(jù),一定會進(jìn)入 CTI
i=0;
while((LPC_UART->LSR&0X01)==1){
Rcv_Buf[buf_i]=LPC_UART->RBR;//接受數(shù)據(jù)
data[i]= Rcv_Buf[buf_i];
i++;
buf_i++;
}
DS1307_Write(data);
break;
}
}
//main.c
#include <LPC11xx.h>
void UARTInit();
void Delay_1s(void);
void UART_Send_Bit(uint8_t data);
void UART_Send(uint8_t str[],int lenght);
void TMR16B0_Init();
void I2CInit();
void DS1307Init();
void Delay_1s();
void DS1307_Read(uint8_t *data);
void Led_init(){
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // 使能時(shí)鐘
LPC_GPIO1->DIR |= (1<<9);
LPC_GPIO1->DATA &= ~(1<<9); //拉低
}
void Delay_1s(){
int i=SystemCoreClock/5;//1s
while(--i);
}
int main(){
SystemInit();// 主時(shí)鐘設(shè)置成 48Mhz
UARTInit();
I2CInit();
Delay_1s();
DS1307Init();
TMR16B0_Init();
while(1){
//UART_Send("11");
}
? ? ? ??《嵌入式系統(tǒng)開發(fā)》系列專欄主要以LPC1100系列微控制器為硬件平臺,詳細(xì)介紹Cortex—-M0微控制器的原理與開發(fā)技術(shù),基于keil仿真軟件平臺設(shè)計(jì)最小應(yīng)用系統(tǒng)板和具有在板仿真器的口袋開發(fā)板以及相關(guān)例程。文章來源:http://www.zghlxwxcb.cn/news/detail-715349.html
? ? ? ??本文已收錄于嵌入式系統(tǒng)開發(fā)系列專欄:嵌入式系統(tǒng)開發(fā) 歡迎訂閱,持續(xù)更新。
到了這里,關(guān)于【嵌入式系統(tǒng)開發(fā)】Keil 實(shí)現(xiàn)十次作業(yè)詳細(xì)代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!