"Zigbee Journey (9)"를 3월 3일에 쓴 후, 저자는 원래 이전에 흩어져 있던 지식들을 요약한 "온도 모니터링 시스템"에 관한 작은 실험을 바로 시작할 계획이었습니다. 하지만 앞서 나온 작은 실험들은 모두 자세히 설명되었음에도 불구하고, 그 코드의 규범적이고 구조적인 성격은 견딜 수 없을 정도라고 할 수 있다는 점도 깨달았다. 요약이기 때문에, 우리는 이전의 작은 지식 포인트를 기계적으로 조합하기보다는 원래의 기반에서 진전을 이루어야 합니다. 그래서 원래 계획을 잠시 미루고, 임베디드 개발의 일반적인 기법을 배우는 데 시간을 들인 뒤 두 편의 에세이를 썼습니다임베디드 C51 프로그래밍 명세서" 그리고 "내장된 프로젝트 코드 구조의 계층 구조》。 이 일지는 Zigbee의 첫 여행 요약일 뿐만 아니라, 최근 며칠간의 저자의 학습 경험도 포함해 Zigbee 초보자들에게 도움이 되길 바랍니다.
전체 텍스트는 소프트웨어 개발의 기본 프로세스에 따라 구성되어 있습니다: 요구사항 분석, 개요 설계, 상세 설계, 코딩 구현, 테스트 등.
1. 수요 분석"고객"과 "개발자" 간의 논의 끝에 다음과 같은 시스템 기능 설명이 결정되었습니다:
… 현재 실내 온도는 CC2430 기반 노드에서 수집되며, PC를 통해 온도 값을 모니터링할 수 있습니다
… CC2430 노드 자체도 일정 수준의 안정성을 가져야 하며, 자동으로 정상 상태로 돌아갈 수 있습니다
… 노드의 샘플링 간격과 전력 관리는 PC가 제어할 수 있습니다
2. 개요 디자인위의 요구사항 분석에 따르면, 시스템을 두 개의 모듈로 나눌 수 있습니다:CC2430 노드그리고PC。
[CC2430 노드]
… 외부 파라미터는 정기적으로 수집되어 PC로 전송할 수 있습니다
… 기계가 꺼졌을 때 자동 초기화
… PC에서 받은 명령은 샘플 간격/전력 관리 변경을 통해 수신 및 처리할 수 있습니다
[PC]
… C 기기는 직렬 포트 도구를 통해 데이터를 수신하고 표시합니다
… 명령어는 직렬 포트 도구를 통해 마이크로컨트롤러에 전송되어 샘플링 속도와 전력 관리를 제어할 수 있습니다
3. 상세 설계(1) 코드 구조
이 시스템의 코드 구조 계층화는 실제로 에세이에서 설명되었습니다.내장된 프로젝트 코드 구조의 계층 구조", 그리고 복사본은 다음과 같습니다:
(1) 하드웨어 추상화 계층
[ioCC2430.h] (시스템 포함):CC2430의 모든 SFR 및 인터럽트 벡터가 정의되어 있습니다
[할.공통 타입 정의, 공통 할당 매크로, CC2430 온칩 자원(I/O, 직렬 통신, ADC, 타이머, 전원 관리 등)의 공통 구성을 포함합니다.
(2) 기능 모듈 계층
[모듈.h온칩 자원(타이머, 입출력 장치), 오프칩 확장 모듈(LED), 그리고 관련 기능의 선언을 정의합니다
[module.c각 모듈(LED)의 초기화를 구현하세요.
(3) 응용 계층
[main.c온도 획득, PC와의 통신, 종료 및 리셋과 같은 특정 응용 요구사항을 충족하려면 hal.h, ioCC2430.h, module.h를 참고하세요
(2) 각 모듈의 구현 방법
개요 설계에 따라 나누어진 모듈에 따라, 내재 시스템은 두 가지 주요 모듈로 나눌 수 있습니다:CC2430 노드그리고PC。
PC에 직렬 포트 통신 도구가 있기 때문에 그 기능은 요구사항을 충족할 수 있으므로, 이 부분을 직접 할 필요가 없고 분석할 필요도 없습니다. 아래에서 CC2430 섹션에 대해 이야기해 보겠습니다
각 부분함수의 구현 방법:
… 타이머의 카운트 오버플로우 인터럽트를 사용해 타이머 샘플링을 트리거합니다
… 직렬 포트가 있는 UART0 모드는 온도 데이터를 PC로 전송합니다
… CC2430에 내장된 워치독 회로는 시스템의 자동 리셋 기능을 구현하는 데 사용됩니다
… 직렬 포트는 PC의 제어 명령을 캡처하고 응답하기 위한 인터럽트를 수신하는 데 사용됩니다
1) 수신 시@이 문자는 샘플링 간격 제어 명령어이며, 그 뒤에 샘플링 간격을 나타내는 숫자가 붙습니다: 0-0.5초, 1-1초, 2-2초
如:@0,表示每隔0.5秒采样一次。
2) 수신 시$ 문자는 슬립 제어 명령어이며, 그 뒤에 전원 모드를 나타내는 숫자가 붙습니다
예를 들어: $3는 시스템을 전원 모드 3으로 전환하는 것을 의미합니다.
(3) 프로그램 플로우차트
- 마스터 프로그램 흐름도
- 타이머 1 오버플로우 인터럽트 프로그램 흐름도
- 직렬 포트 수신 인터럽트 절차의 흐름도
4. 코딩 구현(1) 하드웨어 추상화 계층
하드웨어 추상화 계층에는 ioCC2430.h와 hal.h가 포함됩니다. 전자의 시스템이 포함되어 있기 때문에 목록에 포함되지 않습니다.
다음은 hal.h의 모든 내용 목록입니다(이 파일이 너무 길고 불편해 보이므로 모듈별로 보여드리겠습니다):
- 수장
- 입출력 포트
- 중단됨
- 시리얼 포트
- 전원 및 클럭 관리
- 타이머
- 감시 견인
- 원딜
[url=]
[/url]
/***********************************************************
*파일명: hal.h
*저자: hustlzp
*날짜: 2011년 3월 8일
*판: 1.1
*기능 설명: 하드웨어 추상화 계층
*수정된 기록:
***********************************************************/
#ifndef HAL_H
#defineHAL_H
#include
/***********************************************************
일반적인 타입 정의
***********************************************************/
typedef 서명 없음차어 BYTE;
typedef 서명 없음지능 워드;
typedef 서명 없음길게 DWORD;
/***********************************************************
일반적으로 사용되는 매크로 정의
***********************************************************/
//8위 상승
#defineHIGH_BYTE(a) ((바이트) (((단어)(a)) >> 8))
//8위 하락
#defineLOW_BYTE(a) ((바이트) ((WORD)(a)))
//배속
#defineSET_WORD(regH, regL, 단어)
하다{
(regH)=HIGH_BYTE(단어);
(regL)=LOW_BYTE(단어);
}반면(0)
[url=] [/url]
[url=] [/url]
/***********************************************************
입출력 포트
***********************************************************/
/*I/O 포트 방향을 설정하세요
-----------------------------------------*/
#defineIO_DIR_PORT_PIN(포트, 핀, 감독)
하다{
만약(디어 == IO_OUT)
P##port##DIR |= (0x01<<(핀));
그렇지 않으면
P##port##DIR &= ~(0x01<<(핀));
}반면(0)
//매개변수 dir 값은 다음과 같습니다:
#defineIO_IN 0
#defineIO_OUT 1
/*I/O 포트의 입력 모드를 설정하세요
-----------------------------------------*/
#defineIO_IMODE_PORT_PIN(포트, 핀, 아이모데)
하다{
만약(iMODE == IO_IMODE_TRI)
P##port##INP |= (0x01<<(핀));
그렇지 않으면
P##port##INP &= ~(0x01<<(핀));
}반면 (0)
#define IO_PUD_PORT(포트, 퍼드)
두 {
if (pud == IO_PULLDOWN)
P2INP |= (0x01 << (포트+5));
그렇지 않으면
P2INP &= ~(0x01 << (port+5));
} (0)
매개변수 PUD의 값은 다음과 같습니다:
#define IO_PULLUP 0 // 풀업
#define IO_PULLDOWN 1 // 당겨서 아래로
/*配置I/O口的功能
-----------------------------------------*/
#define IO_FUNC_PORT_PIN(포트, 핀, 펑크)
두 {
if((port == 2) & & (pin == 3)){
만약 (func) {
P2SEL |= 0x02;
} 그렇지 않으면 {
P2SEL &= ~0x02;
}
}
그렇지 않으면 if((port == 2) && (pin == 4)){
만약 (func) {
P2SEL |= 0x04;
} 그렇지 않으면 {
P2SEL &= ~0x04;
}
}
그렇지 않은{
만약 (func) {
P##port##SEL |= (0x01<<(핀));
} 그렇지 않으면 {
P##port##SEL &= ~(0x01<<(pin));
}
}
} (0)
매개변수 함수의 값은 다음과 같습니다:
#define IO_FUNC_GIO 0 // 일반 I/O
#define IO_FUNC_PERIPH 1 // 주변 입출력
주변기기 입출력 위치를 설정하세요
#define IO_PER_LOC_TIMER1_AT_PORT0_PIN234() do { PERCFG = (PERCFG&~0x40)|0x00; } (0)
#define IO_PER_LOC_TIMER1_AT_PORT1_PIN012() do { PERCFG = (PERCFG&~0x40)|0x40; } (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN34() do { PERCFG = (PERCFG&~0x20)|0x00; } (0)
#define IO_PER_LOC_TIMER3_AT_PORT1_PIN67() do { PERCFG = (PERCFG&~0x20)|0x20; } (0)
#define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } (0)
#define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } (0)
#define IO_PER_LOC_SPI1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x08)|0x00; } (0)
#define IO_PER_LOC_SPI1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x08)|0x08; } (0)
#define IO_PER_LOC_SPI0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x00; } (0)
#define IO_PER_LOC_SPI0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x04)|0x04; } (0)
#define IO_PER_LOC_UART1_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x02)|0x00; } (0)
#define IO_PER_LOC_UART1_AT_PORT1_PIN4567() do { PERCFG = (PERCFG&~0x02)|0x02; } (0)
#define IO_PER_LOC_UART0_AT_PORT0_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x00; } (0)
#define IO_PER_LOC_UART0_AT_PORT1_PIN2345() do { PERCFG = (PERCFG&~0x01)|0x01; } (0)
//매개변수 imode의 값은 다음과 같습니다:
#defineIO_IMODE_PUD 0 //당기/당기기
#defineIO_IMODE_TRI 1 //세 개 주[url=] [/url]
[url=] [/url]
/***********************************************************
중단됨
***********************************************************/
//온/오프 인터럽트에 대해
#defineINT_ON 1
#defineINT_OFF 0
//인터럽트 플래그 배치/제거에 사용됩니다
#defineINT_SET 1
#defineINT_CLR 0
//전역 인터럽트 설정
#defineINT_GLOBAL_ENABLE(on) EA=(!! 온)
//구분을 정의하세요
#defineINUM_RFERR 0
#defineINUM_ADC 1
#defineINUM_URX0 2
#defineINUM_URX1 3
#defineINUM_ENC 4
#defineINUM_ST 5
#defineINUM_P2INT 6
#defineINUM_UTX0 7
#defineINUM_DMA 8
#defineINUM_T1 9
#defineINUM_T2 10
#defineINUM_T3 11
#defineINUM_T4 12
#defineINUM_P0INT 13
#defineINUM_UTX1 14
#defineINUM_P1INT 15
#defineINUM_RF 16
#defineINUM_WDT 17
/*중단 허용
-----------------------------------------*/
#defineINT_ENABLE(inum, on)
하다{
만약 (이눔==INUM_RFERR) { RFERRIE = 온; }
그렇지 않으면 만약(이눔==INUM_ADC) { ADCIE = 온; }
그렇지 않으면 만약(이눔==INUM_URX0) { URX0IE = 온; }
그렇지 않으면 만약(이넘==INUM_URX1) { URX1IE = 켜; }
그렇지 않으면 만약(이눔==INUM_ENC) { ENCIE = 온; }
그렇지 않으면 만약(이넘==INUM_ST) { STIE = 온; }
그렇지 않으면 만약(이넘==INUM_P2INT) { (온) ? (IEN2 |=0x02) : (IEN2 &= ~0x02); }
그렇지 않으면 만약(이눔==INUM_UTX0) { (온) ? (IEN2 |=0x04) : (IEN2 &= ~0x04); }
그렇지 않으면 만약(이눔==INUM_DMA) { DMAIE = 온; }
그렇지 않으면 만약(이눔==INUM_T1) { T1IE = on; }
그렇지 않으면 만약(이눔==INUM_T2) { T2IE = on; }
그렇지 않으면 만약(이눔==INUM_T3) { T3IE = 온; }
그렇지 않으면 만약(이눔==INUM_T4) { T4IE = 온; }
그렇지 않으면 만약(이눔==INUM_P0INT) { P0IE = 온; }
그렇지 않으면 만약(이넘==INUM_UTX1) { (온) ? (IEN2 |=0x08) : (IEN2 &= ~0x08); }
그렇지 않으면 만약(이눔==INUM_P1INT) { (온) ? (IEN2 |=0x10) : (IEN2 &= ~0x10); }
그렇지 않으면 만약(이눔==INUM_RF) { (온) ? (IEN2 |=0x01) : (IEN2 &= ~0x01); }
그렇지 않으면 만약(이눔==INUM_WDT) { (온) ? (IEN2 |=0x20) : (IEN2 &= ~0x20); }
}반면 (0)
/*정전 우선순위 설정
-----------------------------------------*/
#defineINT_PRIORITY(그룹, 프리)
하다{
만약(프리 ==0) { IP0 &= ~group; IP1 &= ~group; }
만약(프리 ==1) { IP0 |= 그룹; IP1 &= ~group; }
만약(프리 ==2) { IP0 &= ~group; IP1 |= 그룹; }
만약(프리 ==3) { IP0 |= 그룹; IP1 |= 그룹; }
}반면 (0)
//매개변수 pri의 값은 0/1/2/3(최고 우선순위)입니다.
//매개변수 그룹의 값은 다음과 같습니다:
#defineRFERR_RF_DMA 0x01//그룹 IP0
#defineADC_P2INT_T1 0x02//그룹 IP1
#defineURX0_UTX0_T2 0x04//그룹 IP2
#defineURX1_UTX1_T3 0x08//그룹 IP3
#defineENC_P1INT_T4 0x10//그룹 IP4
#defineST_WDT_P0INT 0x20//그룹 IP5
/*인터럽트 플래그를 받아.
-----------------------------------------*/
#defineINT_GETFLAG(이음) (
(이눔==INUM_RFERR) ? RFERRIF :
(이눔==INUM_ADC) ? ADCIF :
(이눔==INUM_URX0) ? URX0IF :
(이눔==INUM_URX1) ? URX1IF :
(이눔==INUM_ENC) ? ENCIF_0 :
(이눔==INUM_ST) ? STIF :
(이눔==INUM_P2INT) ? P2IF :
(이눔==INUM_UTX0) ? UTX0IF :
(이눔==INUM_DMA) ? DMAIF :
(이눔==INUM_T1) ? T1IF :
(이눔==INUM_T2) ? T2IF :
(이눔==INUM_T3) ? T3IF :
(이눔==INUM_T4) ? T4IF :
(이눔==INUM_P0INT) ? P0IF :
(이눔==INUM_UTX1) ? UTX1IF :
(이눔==INUM_P1INT) ? P1IF :
(이눔==INUM_RF) ? S1CON &= ~0x03 :
(이눔==INUM_WDT) ? WDTIF :
0
)
/*인터럽트 플래그 설정
-----------------------------------------*/
#defineINT_SETFLAG(이음, 여성)
하다{
만약 (이눔==INUM_RFERR) { RFERRIF= f; }
그렇지 않으면 만약(이눔==INUM_ADC) { ADCIF = f; }
그렇지 않으면 만약(이눔==INUM_URX0) { URX0IF = f; }
그렇지 않으면 만약(이넘==INUM_URX1) { URX1IF = f; }
그렇지 않으면 만약(이눔==INUM_ENC) { ENCIF_1 = ENCIF_0 = f; }
그렇지 않으면 만약(이넘==INUM_ST) { STIF = f; }
그렇지 않으면 만약(이넘==INUM_P2INT) { P2IF = f; }
그렇지 않으면 만약(이눔==INUM_UTX0) { UTX0IF= f; }
그렇지 않으면 만약(이눔==INUM_DMA) { DMAIF = f; }
그렇지 않으면 만약(이눔==INUM_T1) { T1IF = f; }
그렇지 않으면 만약(이눔==INUM_T2) { T2IF = f; }
그렇지 않으면 만약(이눔==INUM_T3) { T3IF = f; }
그렇지 않으면 만약(이눔==INUM_T4) { T4IF = f; }
그렇지 않으면 만약(이눔==INUM_P0INT) { P0IF = f; }
그렇지 않으면 만약(이넘==INUM_UTX1) { UTX1IF= f; }
그렇지 않으면 만약(이눔==INUM_P1INT) { P1IF = f; }
그렇지 않으면 만약(이눔==INUM_RF) { (여) ? (S1CON |=0x03) : (S1CON &= ~0x03); }
그렇지 않으면 만약(이눔==INUM_WDT) { WDTIF = f; }
}반면 (0)
[url=] [/url]
[url=] [/url]
/***********************************************************
시리얼 포트
***********************************************************/
//BAUD_E의 값은 서로 다른 보드 속도에 해당합니다
#defineBAUD_E(보드, clkDivPow) (
(보드==2400) ? 6 +clkDivPow :
(보드==4800) ? 7 +clkDivPow :
(보드==9600) ? 8 +clkDivPow :
(보드==14400) ? 8 +clkDivPow :
(보드==19200) ? 9 +clkDivPow :
(보드==28800) ? 9 +clkDivPow :
(보드==38400) ? 10+clkDivPow :
(보드==57600) ? 10+clkDivPow :
(보드==76800) ? 11+clkDivPow :
(보드==115200) ? 11+clkDivPow :
(보드==153600) ? 12+clkDivPow :
(보드==230400) ? 12+clkDivPow :
(보드==307200) ? 13+clkDivPow :
0 )
//BAUD_M의 값은 서로 다른 보드 속도에 해당합니다
#defineBAUD_M(보) (
(보드==2400) ? 59 :
(보드==4800) ? 59 :
(보드==9600) ? 59 :
(보드==14400) ? 216 :
(보드==19200) ? 59 :
(보드==28800) ? 216 :
(보드==38400) ? 59 :
(보드==57600) ? 216 :
(보드==76800) ? 59 :
(보드==115200) ? 216 :
(보드==153600) ? 59 :
(보드==230400) ? 216 :
(보드==307200) ? 59 :
0)
/*UART 모드에서의 직렬 포트 구성
-----------------------------------------*/
#defineUART_SETUP(uart, receiveEnable, baudRate, options)
하다{
만약((우아트) ==0){
만약(PERCFG &0x01){
P1SEL |=0x30;
}그렇지 않으면{
P0SEL |=0x0C;
}
}
그렇지 않으면{
만약(PERCFG &0x02){
P1SEL |=0xC0;
}그렇지 않으면{
P0SEL |=0x30;
}
}
U##uart##GCR = BAUD_E((baudRate),CLKSPD);
U##uart##BAUD = BAUD_M(보도율);
U##uart##CSR |=0x80;
U##uart##CSR |= receiveEnable;
U##uart##UCR |= ((options) |0x80);
}반면(0)
//매개변수 수신 가능 값:
#defineUART_RECEIVE_ENABLE 0x40 //허가 받기
#defineUART_RECEIVE_DISABLE 0x00
//매개변수 옵션의 가치:
#defineFLOW_CONTROL_ENABLE 0x40 //흐름 제어
#defineFLOW_CONTROL_DISABLE 0x00
#defineEVEN_PARITY 0x20 //가끔 확인
#defineODD_PARITY 0x00 //이상한 검증
#defineNINE_BIT_TRANSFER 0x10 //9바이트 전송
#defineEIGHT_BIT_TRANSFER 0x00 //8바이트 전송
#definePARITY_ENABLE 0x08 //패리티 체크 활성화
#definePARITY_DISABLE 0x00
#defineTWO_STOP_BITS 0x04 //2단계 정지 위치
#defineONE_STOP_BITS 0x00 //1 정지 위치
#defineHIGH_STOP 0x02 //정지 레벨이 높아요
#defineLOW_STOP 0x00 //정지 위치는 낮습니다
#defineHIGH_START 0x01 //시작 비트 레벨이 높습니다
#defineLOW_START 0x00 //시작 비트 레벨이 낮습니다
//직렬 포트는 문자를 전송합니다
#defineUART_SEND(uart,data)
하다{
반면(U##uart##CSR &0x01);
U##uart##DBUF = data;
}반면 (0)
#defineUART0_SEND(데이터) UART_SEND(0,data)
#defineUART1_SEND(데이터) UART_SEND(1,데이터)
//직렬 포트는 문자를 받습니다
#defineUART_RECEIVE(uart,data)
하다{
반면(! (U##uart##CSR&0x04));
data=U##uart##DBUF;
}반면(0)
#defineUART0_RECEIVE(data) UART_RECEIVE(0,data)
#defineUART1_RECEIVE(data) UART_RECEIVE(1,data)
[url=] [/url]
[url=] [/url]
/***********************************************************
전원 및 클럭 관리
***********************************************************/
//시계 크로스오버를 얻어
#defineCLKSPD (CLKCON 및 0x07)
//전원 모드 설정하세요
#defineSET_POWER_MODE(모드)
하다{
만약(모드 ==0) { 잠 &= ~0x03; }
그렇지 않으면 만약(모드 ==3) { 잠 |=0x03; }
그렇지 않으면{ 잠 &= ~0x03; SLEEP |= 모드; }
PCON |=0x01;
asm("아니야");
}반면 (0)
//매개변수 모드는 다음과 같은 값으로 설정됩니다:
#definePOWER_MODE_0 0x00
#definePOWER_MODE_1 0x01
#definePOWER_MODE_2 0x02
#definePOWER_MODE_3 0x03
//고주파 RC 발진기의 안정성을 감지하는 데 사용됩니다
#defineHIGH_FREQUENCY_RC_OSC_STABLE (수면 및 0x20)
//결정 발진기의 안정적인 상태를 감지하는 데 사용됩니다
#defineXOSC_STABLE (SLEEP & 0x40)
//타이머의 틱 빈도 값을 얻으세요
#define틱스프드 ((CLKCON 및 0x38) >> 3)
//마스터 클럭 주파수를 설정하세요
#defineSET_MAIN_CLOCK_SOURCE(출처)
하다{
만약(출처) {
CLKCON |=0x40;
반면(! HIGH_FREQUENCY_RC_OSC_STABLE);
만약(틱스프 ==0){
CLKCON |=0x08;
}
잠 |=0x04;
}
그렇지 않으면{
잠 &= ~0x04;
반면(! XOSC_STABLE);
asm("아니야");
CLKCON &= ~0x47;
잠 |=0x04;
}
}반면 (0)
//매개변수 소스의 값은 다음과 같습니다:
#define크리스탈 0x00 //결정 발진기
#defineRC 0x01 //RC 발진기
[url=] [/url]
[url=] [/url]
/***********************************************************
타이머 1
***********************************************************/
//타이머 1은 카운트 오버플로우가 중단되도록 허용합니다
#defineTIMER1_ENABLE_OVERFLOW_INT(발)
(티미프 = (발) ? 티미프 |0x40: 티미프 & ~0x40)
//타이머 1에 오버플로우 인터럽트 플래그를 설정하세요
#defineTIMER1_OVERFLOW_INT_SETFLAG(f) (T1CTL= ((T1CTL & (~0x10)) | f))
//타이머 1 시작
#defineTIMER1_RUN(값) (T1CTL = (값) ? T1CTL|0x02 : T1CTL&~0x03)
//타이머의 시계 분할을 설정하세요
#defineSET_TIMER_TICK(value) do{ CLKCON = ((CLKCON & (~0x38)) | value); } while(0)
//가치의 가치는 다음과 같습니다:
#defineTIMER1_TICK_32M 0x00 //32MHz
#defineTIMER1_TICK_16M 0x08 //16MHz, 시스템 리셋의 기본 값
#defineTIMER1_TICK_8M 0x10 //8MHz
#defineTIMER1_TICK_4M 0x18 //4MHz
#defineTIMER1_TICK_2M 0x20 //2MHz
#defineTIMER1_TICK_1M 0x28 //1MHz
#defineTIMER1_TICK_500k 0x30 //500kHz
#defineTIMER1_TICK_250k 0x38 //250kHz
//TICK 크로스오버를 타이머 1에 설정하세요
#defineSET_TIMER1_TICKDIV(값)
하다{
T1CTL &= ~0x0c;
T1CTL |= 값;
}반면 (0)
//여기서 값은 다음과 같습니다:
#defineTIMER1_TICKDIV_1 0x00 //1 디비전
#defineTIMER1_TICKDIV_8 0x04 //8방향 주파수
#defineTIMER1_TICKDIV_32 0x08
#defineTIMER1_TICKDIV_128 0x0c
//타이머 오버플로우 주기를 설정하세요
#defineSET_TIMER1_PERIOD(값)
하다{
T1CC0H = HIGH_BYTE(값);
T1CC0L = LOW_BYTE(값);
}반면 (0)
//타이머 1의 작동 모드를 설정하세요
#defineSET_TIMER1_MODE(모드)
하다{
T1CTL = ((T1CTL & (~0x03)) | 모드);
}반면 (0)
//모드의 값은 다음과 같습니다:
#defineTIMER1_MODE_STOP 0x00
#defineTIMER1_MODE_FREE 0x01
#defineTIMER1_MODE_MODULE 0x02
#defineTIMER1_MODE_UPDOWN 0x03
[url=] [/url]
[url=] [/url]
/***********************************************************
감시 견인
***********************************************************/
//워치독 타이머의 오버플로우 주기를 설정하세요
#defineWDT_SET_TIMEOUT_PERIOD(타임아웃)
하다{ WDCTL &= ~0x03; WDCTL |= 타임아웃; }반면 (0)
//매개변수 타임아웃의 값은 다음과 같습니다:
#defineSEC_1 0x00 //1초 후
#defineM_SEC_250 0x01 //250ms 후
#defineM_SEC_15 0x02 //15ms 이후
#defineM_SEC_2 0x03 //2ms 후
//개 먹이 주기 절차
#defineWDT_RESET() do {
WDCTL = (WDCTL & ~0xF0) |0xA0;
WDCTL = (WDCTL & ~0xF0) |0x50;
} 반면 (0)
//워치독 타이머 시작/중지
#defineWDT_ENABLE() WDCTL |= 0x08
#defineWDT_DISABLE() WDCTL &= ~0x08
[url=] [/url]
[url=] [/url]
/***********************************************************
원딜
***********************************************************/
//단일 ADC 구성
#defineADC_SINGLE_CONVERSION(설정)
하다{ ADCCON3 = 설정; }반면(0)
//매개변수 설정은 다음과 같은 조합으로 구성됩니다:
//기준 전압
#defineADC_REF_1_25_V 0x00 //내부 1.25V 기준 전압
#defineADC_REF_P0_7 0x40 //AIN7 핀의 외부 기준 전압
#defineADC_REF_AVDD 0x80 //AVDD_SOC 핀
#defineADC_REF_P0_6_P0_7 0xC0 //AIN6-AIN7 차동 입력용 외부 참조 전압
//샘플링 속도
#defineADC_8_BIT 0x00 //8위
#defineADC_10_BIT 0x10 //10위
#defineADC_12_BIT 0x20 //12위
#defineADC_14_BIT 0x30 //14위
//채널 입장
#defineADC_AIN0 0x00 //P0_0
#defineADC_AIN1 0x01 //P0_1
#defineADC_AIN2 0x02 //P0_2
#defineADC_AIN3 0x03 //P0_3
#defineADC_AIN4 0x04 //P0_4
#defineADC_AIN5 0x05 //P0_5
#defineADC_AIN6 0x06 //P0_6
#defineADC_AIN7 0x07 //P0_7
#defineADC_GND 0x0C //토지
#defineADC_TEMP_SENS 0x0E //칩 내 온도 센서
#defineADC_VDD_3 0x0F //VDD/3
ADC 전환이 완료되었습니다
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#endif
//启动ADC转化
#define ADC_START()
Do { ADCCON1 |= 0x40; } (0)//ADC의 트리거 모드를 수동으로 선택하세요(즉, ADC_SAMPLE_READY)
#defineADC_STOP()
하다{ ADCCON1 |=0x30; }반면 (0)[url=] [/url]
(2) 기능 모듈 계층
[url=] [/url]
/***********************************************************
*파일명: module.h
*저자: hustlzp
*날짜: 2011년 3월 6일
*버전: 1.0
*기능 설명: 기능 모듈 계층 헤더 파일
*기능 목록: 공led_init
공허 timer1_init()
공허 uart0_init(공허);
void Uart0SendString(unsigned char *s);
플로트 adc_start(공허)
void get_temperature(부호 없는 char *output, float temp);
공허 watchdog_init(공허);
*수정된 기록:
***********************************************************/
#ifndef MODULE_H
#defineMODULE_H
#include"할."
/***********************************************************
LED
***********************************************************/
//LED 핀을 정의하세요
#defineLED1 P1_0
#defineLED2 P1_1
#defineLED3 P1_2
#defineLED4 P1_3
//LED 불빛과 꺼짐
#defineLED_OFF 1
#defineLED_ON 0
//LED 초기화
공허led_init(공허);
/***********************************************************
타이머1
***********************************************************/
//타이머의 오버플로우 주기 값을 설정하는 데 사용됩니다
#defineTIMER1_OVF_2SEC 0xF424 //2
#defineTIMER1_OVF_1SEC 0x7A12 //1
#defineTIMER1_OVF_dot5SEC 0x3D09 //0.5초
//타이머 1이 초기화됩니다
공허 timer1_init(공허);
/***********************************************************
UART0
***********************************************************/
//UART0 초기화
공허 uart0_init(공허);
//직렬 포트 전송 문자열
공허 Uart0SendString(unsign)차어*s);
/***********************************************************
ADC-14
***********************************************************/
//ADC가 얻은 데이터를 섭씨 온도로 변환하는 데 사용됩니다.
#defineADC_TO_CELSIUS(온도) (온도 * 0.06229 - 311.43)
//ADC 전환 시작
플로트adc_start(공허);
//개종
공허 get_temperature(서명 없음)차어*출력,플로트임시;
/***********************************************************
워치독
***********************************************************/
//워치독 초기화
공허 watchdog_init(공허);
#endif
[url=] [/url]
[url=] [/url]
/***********************************************************
*파일명: module.c
*저자: hustlzp
*날짜: 2011/3/11
*버전: 1.0
*기능 설명: 기능 모듈 계층 소스 파일
*기능 목록: (생략됨)
*수정된 기록:
***********************************************************/
#include"모듈.h"
/***********************************************************
*기능명: led_init
*기능 기능: LED 초기화
*입구 매개변수: 없음
*내보내기 매개변수: 없음
***********************************************************/
공허led_init(공허)
{
//P1.0, P1.1, P1.2, P1.3을 일반 I/O 포트로 구성하세요
IO_FUNC_PORT_PIN(1, 0, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 1, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 2, IO_FUNC_GIO);
IO_FUNC_PORT_PIN(1, 3, IO_FUNC_GIO);
//P1.0, P1.1, P1.2, P1.3을 출력으로 설정하세요
IO_DIR_PORT_PIN(1, 0, IO_OUT);
IO_DIR_PORT_PIN(1, 1, IO_OUT);
IO_DIR_PORT_PIN(1, 2, IO_OUT);
IO_DIR_PORT_PIN(1, 3, IO_OUT);
led1 = LED_ON;
led2 = LED_OFF;
led3 = LED_OFF;
led4 = LED_OFF;
}
/***********************************************************
*기능명: timer1_init
* 기능 기능: 타이머 1 초기화
*입구 매개변수: 없음
*내보내기 매개변수: 없음
***********************************************************/
공허timer1_init(공허)
{
INT_GLOBAL_ENABLE(INT_ON); //글로벌 인터럽션을 열어
INT_ENABLE(INUM_T1, INT_ON); //오픈 T1 인터럽트
TIMER1_ENABLE_OVERFLOW_INT(INT_ON); //열린 T1 카운트 오버플로우 인터럽트
SET_TIMER_TICK(TIMER1_TICK_4M); //타이머 TICK을 4MHz로 설정하세요
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC); //T1의 카운팅 기간을 2로 설정하세요
SET_TIMER1_TICKDIV(TIMER1_TICKDIV_128); //T1의 클럭 크로스오버를 128로 설정하세요
SET_TIMER1_MODE(TIMER1_MODE_MODULE); //T1의 실행 모드를 모듈로 설정하세요
}
/***********************************************************
*기능명: uart0_init
*함수 기능: 직렬 포트 UART0 초기화
*입구 매개변수: 없음
*내보내기 매개변수: 없음
***********************************************************/
공허uart0_init(공허)
{
//UART 위치를 선택하세요
IO_PER_LOC_UART0_AT_PORT0_PIN2345();
//UART 구성 완료: 수신 허용, 115200bps, 1비트 정지 비트, 패리티 없음
UART_SETUP(0, UART_RECEIVE_ENABLE,115200, ONE_STOP_BITS | PARITY_DISABLE);
//완전한 중단을 열어
INT_GLOBAL_ENABLE(INT_ON);
//인터럽트를 받기 위해 시리얼 포트 0을 열어
INT_ENABLE(INUM_URX0, INT_ON);
}
/***********************************************************
*함수명: Uart0SendString
* 기능 기능: 타이머 1 초기화
*항목 매개변수: 부호 없는 문자 *s
보내고 싶은 실이
*내보내기 매개변수: 없음
***********************************************************/
공허Uart0SendString(unsign)차어*s)
{
반면(*s !=0)
UART0_SEND(*s++);
}
/***********************************************************
*기능명: adc_start
*기능 기능: ADC 변환 시작
*입구 매개변수: 없음
*내보내기 매개변수: float
태블릿의 온도 값
***********************************************************/
플로트adc_start(공허)
{
서명 없음지능임시;
//기준 전압은 1.25V이며, 샘플링 정확도는 14비트이며, 변환 대상은 온칩 온도 센서입니다
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS);
ADC_STOP(); //ADC를 수동으로 변환할 트리거 메서드를 설정하세요
ADC_START(); //ADC 전환 시작
반면(! ADC_SAMPLE_READY()); //변환이 완료될 때까지 기다려
temp = ADCL >>2; //변환 결과를 temp로 저장하세요
임시 |= (((부호 없음)지능) ADCH) <<6);
귀환ADC_TO_CELSIUS(임시직); //변환 후 실제 온도 값을 반환합니다
}
/***********************************************************
*함수명: get_temperature
*함수 함수: 온도 값을 처리하여 직렬 출력을 위해 문자 배열에 저장함
*항목 매개변수: 부호 없는 문자 *출력
변환된 온도 값을 저장하는 데 사용됩니다
부표 온도
섭씨 온도 값
*내보내기 매개변수: 없음
***********************************************************/
공허get_temperature(서명 없음)차어*출력,플로트임시)
{
출력[0] = (부호 없는차어(임시) /10 + 48; //열 자리
출력[1] = (부호 없는차어(임시) %10 + 48; //한 자릿수
출력[2] ='.'; //소수점
출력[3] = (부호 없는차어(임시*10) %10 + 48; //열 번째
출력[4] = (부호 없는차어(임시*100) %10 + 48; //백분위
출력[5] =''; //끈 끝자
}
/***********************************************************
*기능명: watchdog_init
*함수 기능: 워치독 초기화
*입구 매개변수: 없음
*내보내기 매개변수: 없음
***********************************************************/
공허watchdog_init(공허)
{
WDT_SET_TIMEOUT_PERIOD(SEC_1); //타임아웃 시간을 1초로 설정하세요
WDT_ENABLE(); //감시견을 시작하세요
}
[url=] [/url]
(3) 응용 계층
[url=] [/url]
/*******************************************************************
파일명: main.c
저자: hustlzp
날짜: 2011/3/11
버전: 1.0
기능 설명: 마스터 프로그램 파일
기능 목록: (생략됨)
수정 기록:
*******************************************************************/
#include
/********************************************************************
인터럽트 서비스 절차
********************************************************************/
/* 定时器1溢出中断子程序
-------------------------------------------------------*/
#pragma 벡터=T1_VECTOR
__interrupt 보이드 T1_ISR(보이드)
{
EA=0; 문이 끊긴다
led2 = LED_ON;
get_temperature(output,adc_start()); 온도 값을 출력할 문자 배열로 변환하세요
Uart0SendString(output); 출력 온도 값
Uart0SendString("°C");
LED2
/* 串口接收中断子程序
-------------------------------------------------------*/
#pragma 벡터=URX0_VECTOR
__interrupt 보이드 RE_ISR(void)
{
EA=0;
led3 = LED_ON;
수신 = U0DBUF;
if(type==1) // type=1, 수신된 문자가 타이머 오버플로우 주기를 설정하는 데 사용됨을 나타냅니다
{
유형=0;
스위치(수신)
{
케이스 '0': // 타이머 초과 주기는 0.5초입니다
{
SET_TIMER1_PERIOD(TIMER1_OVF_dot5SEC);
브레이크;
}
케이스 '1': // 타이머 초과 기간은 1초입니다
{
SET_TIMER1_PERIOD(TIMER1_OVF_1SEC);
브레이크;
}
케이스 '2': // 타이머 초과 주기는 2초입니다
{
SET_TIMER1_PERIOD(TIMER1_OVF_2SEC);
브레이크;
}
}
}
그렇지 않으면 IF(type==2) // type=2, 수신된 문자가 절전 제어에 사용됨을 나타냅니다
{
유형=0;
led1 = LED_OFF;
led2 = LED_OFF;
led3 = LED_OFF;
스위치(수신)
{
케이스 '1': // 전원 모드 PM1 입력
{
SET_POWER_MODE(1);
브레이크;
}
케이스 '2': // 전원 모드 PM2 입력
{
SET_POWER_MODE(2);
브레이크;
}
케이스 '3': //전원 모드 PM3 입력
{
SET_POWER_MODE(3);
브레이크;
}
}
}
그렇지 않으면 IF(type==0) // type=0, 이는 수신된 문자가 제어 명령의 유형임을 나타냅니다: @ 또는 $
{
if(receive=='@')
{
타입=1; '@'는 다음 문자가 넘겨주기를 설정하는 데 사용되었음을 나타냅니다
}
그렇지 않으면 (receive=='$')
{
유형=2; '$'가 수신되며, 다음 문자가 시스템 슬립 제어에 사용됨을 나타냅니다
}
}
led3 = LED_OFF;
EA=1;
}
=LED_OFF;
TIMER1_OVERFLOW_INT_SETFLAG(INT_CLR); 방해 표지판을 치워
EA=1; 오픈 인터럽트
}
/* 主函数
-------------------------------------------------------*/
보이드 메인(보이드)
{
SET_MAIN_CLOCK_SOURCE(크리스탈); 시스템 클럭을 32MHz 크리스털 발진기로 설정하세요
led_init(); LED 초기화
uart0_init(); 직렬 포트 UART0 초기화
timer1_init(); 타이머 1이 초기화됩니다
watchdog_init(); 워치독 초기화
while(1)
{
WDT_RESET(); 개에게 계속 밥을 주세요
}
}/********************************************************************
주요 프로그램
********************************************************************/
/* 全局变量
-------------------------------------------------------*/
부호 없는 문자 출력[6]={0}; 온도 데이터는 쉽게 직렬 출력을 위해 저장됩니다
미사인 샤 리시브; 수신한 문자를 저장하세요
부호 없는 char 유형=0; 수신된 문자의 타입 플래그는 0/1/2로 설정되어 있습니다"모듈.h"[url=] [/url]
5. 시험오~ 드디어 코드가 붙여넣어졌네요, 정말 피곤하네요, 이 작은 시스템을 테스트해봅시다:
(1) 시간 표본 추출
직렬 포트를 열고 IAR 디버깅을 시작하면 LED1이 켜져 있고, 직렬 포트 도구의 온도 값이 지속적으로 생성되며, 샘플링 간격이 2초로 결정됩니다:
(2) 샘플링 간격 제어
시리얼 포트 도구에서 "@1"을 입력한 후 샘플링 구간을 테스트하면 1이 된 것을 확인하면; "@0"을 입력하면 샘플링 간격이 0.5초로 바뀌었습니다.
(3) 수면 조절
시리얼 포트 도구에 "$1"을 입력하면 모든 LED가 꺼져 있고 온도 샘플링도 멈췄습니다:
테스트 후 시스템은 정상적이고 안정적으로 작동하며 기본적으로 요구사항을 충족합니다.
소스 코드가 필요한 학생들다운로드하려면 여기를 클릭하세요
6. 결론이 논문은 비교적 포괄적인 실험을 예시로 삼아 CC2430 온칩 자원을 통합하여 비교적 표준화된 소형 시스템을 작성하는 방법을 보여준다. 며칠 후, 저와 모두가 CC2430을 쉽게 사용할 수 있도록 hal.h용 간단한 사용자 매뉴얼을 작성할 예정입니다.
다음으로는 CC2430 온칩 자료에 대한 연구를 마무리하고 TI Z-Stack 프로토콜 스택을 배우는 데 전념할 것입니다~
이 시리즈의 블로그 글은 일단 마무리되었지만, 지그비의 여정은 계속될 것입니다. 앞으로의 풍경은 알 수 없지만, 저는 작가가 모두와 함께 장애물을 극복하고 기복을 맛보며 얻을 것이라 믿습니다.
계속 지켜봐 주세요: "TI Z-Stack에 가입하세요" 블로그 게시물!